1. 程式人生 > >BZOJ5177: [Jsoi2013]貪心的導遊

BZOJ5177: [Jsoi2013]貪心的導遊

總數 購物 mat ret 一點 不能 turn 謙虛 商品

Description

南京有一條著名的購物街。購物街嘛,就是一排整齊的商店啦~ 導遊小Z每次都會把遊客團帶到購物街裏走一段,然後選擇一個商店進去購物。小Z接待的遊客都是購物狂,他們恨 不得將店內的商品洗劫一空,也就是說,只要他們能買,就一定會繼續買(錢夠不夠你不用考慮,他們都有信用卡 可以透支)。但是有一點,他們都非常講究平等、很謙虛,每個人都不能忍受比別人多買什麽東西或者少買什麽東 西,於是他們每個人最後買的商品數量都是一樣的。這雖然導致他們沒辦法每次都把商店搬空,但是每次已經給店 家帶來一大筆生意了,店家已經非常感謝了!為了表示感謝,店家決定把遊客們買完之後剩下來那幾件沒賣掉的商 品就送給導遊小Z了。貪心的小Z自然希望自己能獲贈的商品數量越大越好啦~現在告訴你這一排共n個商店(標號為 0到n-1)每個商店裏的商品總數,每次小Z會帶一批共p個遊客的旅遊團,到其中u號商店和v號商店之間逛一逛,請 你幫小Z在所逛的商店區間內選擇一個,告訴小Z他最多能獲贈多少件商品。

Input

第一行,包含兩個整數n、m,分別表示商店個數、小Z帶來的旅遊團個數。 接下來一行,包含n個整數ai(i=0,1,……,n-1),表示第i個商店的商品總數。 接下來m行,每行三個整數u、v、p(0≤u,v≤n-1,2≤p≤1000) 表示這個旅遊團逛u號商店和v號商店之間的商店(包含u、v),且這個旅遊團的人數為p。 n≤1000000, m≤50000, 0≤ai≤1000, 2≤p≤1000

Output

共輸出m行,每行一個整數,第i行輸出第i個旅遊團購物後,小Z最多能獲贈的商品數量。

Sample Input

5 5
2 4 6 8 10
0 1 2
1 4 3
2 4 2
1 1 9
0 4 7

Sample Output

0
2
0
4
6
第一個旅遊團, 2 個人, 0 號商店到 1 號商店的區間。若去 1 號商店,共 2 件商品,每人買 1 件,剩 0 件
。若去 2 號商店,共 4 件商品,每人買 2 件,剩 0 件。所以,小 Z 最多獲贈 0 件。
第二個旅遊團, 3 個人,小 Z 選擇帶他們去 4 號商店,共 8 件商品,每人買 2 件商品(因為每人 3 件不夠)
,剩下 2 件,小 Z 最多獲贈就是 2 件。 可以驗證去其它商店小 Z 最多獲贈的商品不會達到 2 件。
題目傳送門 話說A這種題目很爽啊~~~ 今天早上翻出來這道題,看了看,就想暴力 暴力求出每個數mod1~1000的值,用主席樹查最大值,然後在班上吼了一嗓子。。。 結果隔壁的肉絲也開始搞這個,他竟然做的比我快!!(這就是你頹飛劍問道的原因???) 然後一看內存,哎呀媽呀,這n<=1000000是要上天。。。 其實這個還是可以用主席樹做的,同樣從p下手即可 枚舉一下問問主席樹這東西在不在即可 40s的題真親切 代碼如下:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
struct ZhuXi{
    int lc,rc,c;
}t[21000000];int cnt;
int rt[2100000];
void Link(int &u,int l,int r,int p)
{
    if(u==0)u=++cnt;
    t[u].c++;
    if(l==r)return ;
    int mid=(l+r)/2;
    if(p<=mid)Link(t[u].lc,l,mid,p);
    else Link(t[u].rc,mid+1,r,p);
}
void merge(int &u1,int u2)
{
    if(u1==0){u1=u2;return ;}
    if(u2==0)return ;
    t[u1].c+=t[u2].c;
    merge(t[u1].lc,t[u2].lc);
    merge(t[u1].rc,t[u2].rc);
}
int findans(int u1,int u2,int l,int r,int k)
{
    if(t[u1].c-t[u2].c==0)return 0;
    if(l==r)return l;
    int lcx=t[u1].lc,rcx=t[u1].rc,lcy=t[u2].lc,rcy=t[u2].rc;
    int mid=(l+r)/2;
    if(k<=mid)return findans(lcx,lcy,l,mid,k);
    else 
    {
        int tmp=findans(rcx,rcy,mid+1,r,k);
        if(tmp==0)return findans(lcx,lcy,l,mid,k);
    }
}
int n,m;
int main()
{
    scanf("%d%d",&n,&m);cnt=0;
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        Link(rt[i],0,2000,x);
        merge(rt[i],rt[i-1]);
    }
    while(m--)
    {
        int u,v,p;int ans=0;
        scanf("%d%d%d",&u,&v,&p);u++,v++;
        for(int i=1;i*p<=2000;i++)
            ans=max(ans,findans(rt[v],rt[u-1],0,2000,p*i-1)-p*(i-1));
        printf("%d\n",ans);
    }
    return 0;
} 

by_lmy

BZOJ5177: [Jsoi2013]貪心的導遊