【NOIP模拟】旷野大计算

Description

【NOIP模拟】旷野大计算_第1张图片

**Solution

这是一道套路题,不过我现在才学会套路。
对于莫队算法,进队统计答案很快,出队统计答案很慢的情况有一个套路:把所有的出队变成进队,每次询问的[l,r],把l放到l所在的块的末尾为l’,然后把l到l’-1的都入队,更新答案,因为右端点是递增的,所以右边就逐个进队就好了,然后结束的时候就把l’到l-1退队。每次l换块的时候,就把所有的数据暴力重构。

Code

#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=100007;
typedef long long ll;
int i,j,k,l,t,n,m,da,kuai[maxn],r,num,g[maxn],d[maxn],tot;
ll ans2,ans,ans1[maxn];
int c[maxn];
struct node{
    int a,b,c;
}b[maxn],q[maxn];
struct nod{
    int x,y;
}a[maxn];
bool cmp(node x,node y){
    return kuai[x.a]y.a]||kuai[x.a]==kuai[y.a]&&x.b<y.b;
}
bool cmp1(nod x,nod y){
    return x.x<y.x;
}
bool cmp2(node x,node y){
    return x.a<y.a||x.a==y.a&&x.b<y.b;
}
void jin(int x){
    c[g[x]]++;
    if((ll)d[g[x]]*c[g[x]]>ans)ans=(ll)d[g[x]]*c[g[x]];
}
void chu(int x){
    c[g[x]]--;
/*  int i;
    fo(i,1,num){
        ans=max(d[g[i]]*c[g[i]],ans);
    }*/
}
int main(){
//  freopen("fan.in","r",stdin);
   // freopen("fan.out","w",stdout);    
    scanf("%d%d",&n,&m);
    da=sqrt(n);
    fo(i,1,n)scanf("%d",&a[i].x),a[i].y=i,kuai[i]=(i-1)/da+1;
    sort(a+1,a+1+n,cmp1);
    d[++num]=a[1].x;g[a[1].y]=1;
    fo(i,2,n){
        if(a[i].x!=a[i-1].x){
            d[++num]=a[i].x,g[a[i].y]=num;
        }
        else g[a[i].y]=num;
    }
    fo(i,1,m){
        scanf("%d%d",&b[i].a,&b[i].b);b[i].c=i;
    }
    sort(b+1,b+1+m,cmp);
    l=0;
    fo(j,1,m){
        if(b[j].a==b[j].b){
            q[++tot].a=b[j].a;
            q[tot].b=b[j].b;
            q[tot].c=b[j].c;
            continue;
        }
        if(kuai[l]!=kuai[b[j].a]){
            ans=0;
            fo(i,1,num)c[i]=0;
            l=kuai[b[j].a]*da,r=b[j].b;
            fo(i,l,r)jin(i);
            ans2=ans;
        }
        ans=ans2;l=kuai[b[j].a]*da;
        while(rwhile(l>b[j].a)jin(--l);ans1[b[j].c]=ans;
        fo(i,b[j].a,kuai[b[j].a]*da-1)chu(i);
    }
    sort(q+1,q+1+tot,cmp2);
    l=0;
    fo(j,1,m){
        if(l<q[j].a){
            ans=0;
            fo(i,1,num)c[i]=0;
            l=q[j].a,r=q[j].b;
            fo(i,l,r)jin(i);
        }
        else{
            fo(i,r+1,q[j].b)jin(i);
        }
        ans1[q[j].c]=ans;
    }
    fo(i,1,m)printf("%lld\n",ans1[i]);
}

你可能感兴趣的:(noip,分块大法,莫队算法)