HDU5808 Price List Strike Back

分治
類似ZJOI2016的最短路分治思想
媽的有毒
極大值有毒

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<algorithm>
#include<stack>
#include<vector>
using namespace std;
char c;
inline void read(int&a){a=0;do c=getchar();while(c<'0'||c>'9');while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}

struct Query
{
    int l,r,C,sum,no;
    bool ans;
}Q[200001];
inline bool cmp(Query a,Query b){return a.no<b.no;}
inline int Min(int&a,int b){return a>b?a=b:a;}

int w[200001],d[200001];
int G[20001][101],F[20001][101];
const
    int INF=1<<30;
void Solve(int l,int r,int L,int R,bool lp)
{

    if(l==r)
    {
        for(int i=L;i<=R;i++)
            Q[i].ans=(Q[i].sum==w[l]&&d[l]<=Q[i].C);
        int *A=lp?F[l]:G[l];
        for(int i=1;i<=100;i++)
        A[i]=INF;
        A[w[l]]=d[l];   
        return;
    }
    int Mid=l+r>>1;
    static Query Ca[200001];
    int cnt=0,cnt2,cnt3;
    for(int i=L;i<=R;i++)
        if(Q[i].r<=Mid)
            Ca[++cnt]=Q[i];
    cnt2=cnt;
    for(int i=L;i<=R;i++)
     if(Q[i].l>Mid)
            Ca[++cnt2]=Q[i];
    cnt3=cnt2;
    for(int i=L;i<=R;i++)
        if(Q[i].l<=Mid&&Q[i].r>Mid)
            Ca[++cnt3]=Q[i];
    for(int i=L;i<=R;i++)
        Q[i]=Ca[i-L+1];
    Solve(l,Mid,L,L+cnt-1,1);
    Solve(Mid+1,r,L+cnt,L+cnt2-1,0);

    for(int i=L+cnt2;i<=R;i++)
    {
        int Mi=INF;
        for(int j=0;j<=Q[i].sum;j++)
            Min(Mi,max(F[Q[i].l][j],G[Q[i].r][Q[i].sum-j]));
        Q[i].ans=Mi<=Q[i].C;
    }

    if(!lp)
    {

        for(int j=1;j<=100;j++)
            G[l][j]=INF;
        G[l][w[l]]=d[l];
        for(int i=l+1;i<=r;i++) 
            {
                for(int j=1;j<=100;j++)
                    {
                        G[i][j]=G[i-1][j];
                        if(j>=w[i])
                            Min(G[i][j],max(G[i-1][j-w[i]],d[i]));
                    }
            }
    }

    else
    {

        for(int j=1;j<=100;j++)
            F[r][j]=INF;
        F[r][w[r]]=d[r];
        for(int i=r-1;i>=l;i--) 
            {
                for(int j=1;j<=100;j++)
                    {
                        F[i][j]=F[i+1][j];
                        if(j>=w[i])
                            Min(F[i][j],max(F[i+1][j-w[i]],d[i]));
                    }
            }

    }
}



int main()
{
    int t;
    read(t);
    while(t--)
    {
        int n,m;
        read(n),read(m);
        for(int i=1;i<=n;i++)read(w[i]);
        for(int i=1;i<=n;i++)read(d[i]);
        for(int i=1;i<=m;i++)
            read(Q[i].l),read(Q[i].r),read(Q[i].C),read(Q[i].sum),Q[i].no=i;
        Solve(1,n,1,m,0);
        sort(Q+1,Q+1+m,cmp);
        for(int i=1;i<=m;i++)
            putchar(Q[i].ans?'0':'1');
        puts("");
    }


    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章