zoukankan      html  css  js  c++  java
  • [EOJ439] 强制在线

    Description

    EOJ439

    Solution

    先考虑不强制在线怎么做。

    按询问区间右端点排序,从左往右扫,维护所有后缀的答案。

    如果扫到 (a[i]),那么让统计个数的 (cnt[a[i]]++).

    如果(cnt[a[i]]<a[i]),那么在当前的右端点固定的情况下这个(a[i])不会有任何的贡献。

    如果(cnt[a[i]]=a[i]),那么可以让([1,pre[i]])区间加(1),其中(pre[i])代表从(i)向前第(a[i])(a[i])出现的位置。

    如果(cnt[a[i]]>a[i]),那么需要让((pos[pos[pre[i]]],pos[pre[i]]])区间减(1),其中(pos[i])代表从(i)向前第(1)(a[i])出现的位置,同时还需要让((pos[pre[i]],pre[i]])区间加(1)

    这个放上线段树区间修改单点查询就好了。

    但是要求强制在线。

    推上主席树。

    还要区间修改。

    pushdown空间巨大?

    标记永久化。

    Code

    #include<set>
    #include<map>
    #include<cmath>
    #include<queue>
    #include<cctype>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using std::min;
    using std::max;
    using std::swap;
    using std::vector;
    const int N=1e5+5;
    typedef double db;
    const int maxn=1e5;
    typedef long long ll;
    #define pb(A) push_back(A)
    #define pii std::pair<int,int>
    #define all(A) A.begin(),A.end()
    #define mp(A,B) std::make_pair(A,B)
    
    vector<int> v[N];
    int n,q,a[N],sum[N*30],cov[N*30];
    int root[N],ch[N*30][2],cnts[N],tot;
    
    int getint(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch))w|=ch=='-',ch=getchar();
        while( isdigit(ch))X=X*10+ch-48,ch=getchar();
        if(w) return -X;return X;
    }
    
    int modify(int pre,int l,int r,int ql,int qr,int c){
        int cur=++tot;
        ch[cur][0]=ch[pre][0];ch[cur][1]=ch[pre][1];
        sum[cur]=sum[pre]+c*(qr-ql+1);cov[cur]=cov[pre];
        if(ql<=l and r<=qr){
            cov[cur]+=c;
            return cur;
        } int mid=l+r>>1;
        if(qr<=mid) ch[cur][0]=modify(ch[pre][0],l,mid,ql,qr,c);
        else if(ql>mid) ch[cur][1]=modify(ch[pre][1],mid+1,r,ql,qr,c);
        else{
            ch[cur][0]=modify(ch[pre][0],l,mid,ql,mid,c);
            ch[cur][1]=modify(ch[pre][1],mid+1,r,mid+1,qr,c);
        } return cur;
    }
    
    int query(int cur,int l,int r,int ql,int qr,int add){
        if(ql<=l and r<=qr) return sum[cur]+add*(r-l+1);
        int mid=l+r>>1;
        if(qr<=mid) return query(ch[cur][0],l,mid,ql,qr,add+cov[cur]);
        else if(ql>mid) return query(ch[cur][1],mid+1,r,ql,qr,add+cov[cur]);
        else return query(ch[cur][0],l,mid,ql,mid,add+cov[cur])+query(ch[cur][1],mid+1,r,mid+1,qr,add+cov[cur]);
    }
    
    signed main(){
        n=getint(),q=getint();
        for(int i=1;i<=n;i++) v[i].pb(0);
        for(int i=1;i<=n;i++){
            a[i]=getint();
            root[i]=root[i-1];
            if(a[i]>n)
                continue;
            cnts[a[i]]++;
            v[a[i]].pb(i);
            if(cnts[a[i]]==a[i])
                root[i]=modify(root[i],1,n,1,v[a[i]][1],1);
            else if(cnts[a[i]]>a[i]){
                int sze=v[a[i]].size();
                root[i]=modify(root[i],1,n,v[a[i]][sze-a[i]-2]+1,v[a[i]][sze-a[i]-1],-1);
                root[i]=modify(root[i],1,n,v[a[i]][sze-a[i]-1]+1,v[a[i]][sze-a[i]],1);
            }
        } int lasans=0;
        while(q--){
            int x=getint()^lasans,y=getint()^lasans;
            printf("%d
    ",lasans=query(root[y],1,n,x,x,0));
        } return 0;
    }
    
  • 相关阅读:
    整理打印PI值
    使用自连接、for xml path('')和stuff合并显示多行数据到一行中(转)
    ThinkPHP+jQuery EasyUI Datagrid查询数据的简单处理
    ThinkPHP学习(三)
    Apache+PHP配置PATHINFO的一个小问题
    ThinkPHP学习(二)
    接口签名工具类
    RSA加密和解密工具类
    kafka项目中踩到的一个坑(客户端和服务器端版本不一致问题)
    自己实现字符串转整数(不使用JDK的字符串转整数的方法)
  • 原文地址:https://www.cnblogs.com/YoungNeal/p/9857615.html
Copyright © 2011-2022 走看看