zjnu 1762 U(想法 線段樹)

2021-07-10 16:30:03 字數 1306 閱讀 2712

題目大意:

有n道菜,每道菜分別有兩種**a和b。如果要買k道菜,則除了第一道要花a的**以外,其他的k-1道菜都以b的**買下。現在要分別得到買1~n道菜要花的最少的錢。

範圍:n<=50w。

思路:錢要花最少,在買多道菜的時候我們自然是希望b的**越小越好。所以我們可以先對菜的**按照b從小到大排個序。

對於n道菜,如果我們買k道菜,可以分兩種情況。

1.在前k 道菜裡面買,那麼我們可以知道,總共要花的錢是a+(k-1)*b。轉化一下就是k*b+a-b。既然我們已經對b排序了,所以直接選取前k個就能保證最小,然後就是要a-b最小。當然我們也可以通過預處理排序得到。

2.在前k道菜裡面買k-1道,剩下的一道菜在後面的菜裡面選。同時要讓後面選中的菜是第一道。這樣我們就可以找出後面的菜裡面a最小的一道,加上前k-1道**為b的菜。找a的最小這裡可以用線段樹處理。

然後在兩者裡面選小的就可以了。

**:#include#include#include#include#include#define ll __int64

#define m 500005

#define inf 1000000007

using namespace std;

struct node

p[m];

struct node1

pp[m];

ll pre[m];

struct treetree[m<<2];

bool cmp(node x,node y)

int query(int l,int r,int i)

int mid=tree[i].l+tree[i].r>>1;

if(r<=mid)return query(l,r,i<<1);

else if(l>mid)return query(l,r,i<<1|1);

else return min(query(l,mid,i<<1),query(mid+1,r,i<<1|1));

}int main()

sort(p+1,p+1+n,cmp);

for(i=1;i<=n;i++)

sort(pp+1,pp+1+n,cmp1);

for(i=1;i<=n;i++)

build(1,n,1);

ll minnow=mp2[1];

int xx=1;

for(k=1;k<=n;k++)

{ans1=ans2=0;

ans1+=pre[k-1];

ans1+=query(k,n,1);

ans2+=pre[k];

if(mp2[k]

zjnu 1182 能量項鍊

這道題和石子歸併其實是同樣的題目。題意 那邊寫的不是很清楚 首先給你n個珠子,每個珠子都有兩個屬性,分別是頭標記與尾標記,然後分別給出n個數,分別代表的是這些珠子的頭標記。前一顆珠子的尾標記一定等於後一顆珠子的頭標記。如果前一顆能量珠的頭標記為m,尾標記為r,後一顆能量珠的頭標記為r,尾標記為n,則...

ZJNU 1067 約瑟夫 中級

打表處理 case 1超時 對m進行列舉,每次列舉進行一次判斷 因為好人壞人均為k個,那麼只要讓下乙個死亡的人的位置p保證在1 剩餘壞人數量之間即可,不滿足則直接break列舉下乙個m 實際上對於m,因為m必須是 2kc 1,2kc k c n 之間的數,所以還能再優化,但下面的 已經能夠在78ms...

ZJNU 統計數字(1402)

description 某次科研調查時得到了n個自然數,每個數均不超過1500000000 1.5 10 9 已知不相同的數不超過10000個,現在需要統計這些自然數各自出現的次數,並按照自然數從小到大的順序輸出統計結果。input 第1行是整數n,表示自然數的個數。第2 n 1行每行乙個自然數。o...