zoukankan      html  css  js  c++  java
  • P4887 第十四分块(前体)

    P4887 第十四分块(前体)

    链接

    P4887 第十四分块(前体)

    题解

    二次离线莫队。。新技能get。。
    用于可以使用莫队且单次转移的效率不是 (O(1)) 的情况。
    对于每次指针移动,先不直接算,而是把询问差分然后再次离线询问。
    这样可以算出每一问对于上一个询问的答案的变化量,最后再重新按末对的顺序加起来就可以。

    (Code)

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int N=1e5+10;
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    void print(LL x){
        if(x>9) print(x/10);
        putchar(x%10+'0');
    }
    
    int n,m,K,B; 
    int a[N],be[N];
    struct query{
    	int l,r,id;
    }q[N];
    bool cmp(query x,query y){
    	if(be[x.l]!=be[y.l]) return be[x.l]<be[y.l];
    	return x.r<y.r;
    }
    //pre[x][0]=f(x,[1,x-1]) pre[x][1]=f(x,[1,x])
    LL pre[N][2],s[N];
    LL ans[N];
    vector<int> c;
    struct P{
    	int l,r,id,f;
    	P(int lx=0,int rx=0,int idx=0,int fx=0){
    		l=lx;r=rx;id=idx;f=fx;
    	}
    };
    vector<P> ve[N];
    int main(){
    	scanf("%d%d%d",&n,&m,&K);B=sqrt(n);
    	for(int i=1;i<=n;++i) {
    		scanf("%d",&a[i]);
    		be[i]=(i+B-1)/B;
    	}
    	for(int i=1;i<=m;++i){
    		scanf("%d%d",&q[i].l,&q[i].r);q[i].id=i;
    	}
    	sort(q+1,q+1+m,cmp);
    	for(int i=0;i<16384;++i) 
    		if(__builtin_popcount(i)==K) c.push_back(i);
    	for(int i=1;i<=n;++i){
    		for(int j=0;j<c.size();++j) ++s[a[i]^c[j]];
    		pre[i+1][0]=s[a[i+1]];pre[i][1]=s[a[i]];
    	}
    	memset(s,0,sizeof(s));
    	int l=1,r=0;
    	for(int i=1;i<=m;++i){
    		if(r<q[i].r) ve[l-1].push_back(P(r+1,q[i].r,q[i].id,-1));
    		while(r<q[i].r){++r;ans[q[i].id]+=pre[r][0];} 
    		//r++ f(x,[l,x-1])=f(x,[1,x-1])-f(x,[1,l-1])
    		if(l>q[i].l) ve[r].push_back(P(q[i].l,l-1,q[i].id,1));
    		while(l>q[i].l){--l;ans[q[i].id]-=pre[l][1];}
    		//l-- f(x,[x+1,r])=f(x,[1,r])-f(x,[1,x])
    		if(r>q[i].r) ve[l-1].push_back(P(q[i].r+1,r,q[i].id,1));
    		while(r>q[i].r){ans[q[i].id]-=pre[r][0];--r;} 
    		//r-- -f(x,[l,x-1])=-f(x,[1,x-1])+f(x,[1,l-1])
    		if(l<q[i].l) ve[r].push_back(P(l,q[i].l-1,q[i].id,-1));
    		while(l<q[i].l){ans[q[i].id]+=pre[l][1];++l;}
    		//l++ -f(x,[x+1,r])=-f(x,[1,r])+f(x,[1,x])
    	}
    	for(int i=1;i<=n;++i){
    		for(int j=0;j<c.size();++j) ++s[a[i]^c[j]];
    		for(int j=0;j<ve[i].size();++j){
    			for(int k=ve[i][j].l;k<=ve[i][j].r;++k){
    				ans[ve[i][j].id]+=(LL)ve[i][j].f*s[a[k]];
    			}
    		}
    	}
    	for(int i=2;i<=m;++i){
    		ans[q[i].id]+=ans[q[i-1].id]; 
    	}
    	for(int i=1;i<=m;++i) {
    		print(ans[i]);
    		puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    jquery处理鼠标左中右键事件
    bootstrap弹出框
    移动端去掉a标签点击时出现的背景
    sessionStorage
    页面滑动到最下面,执行代码
    判断页面时向上滚动还是向下滚动
    sql 时间查询 /sql中判断更新或者插入/查询一年所有双休日
    求取最大值
    Repeater 获取数据值
    加载完毕后执行计算
  • 原文地址:https://www.cnblogs.com/Yuigahama/p/13519215.html
Copyright © 2011-2022 走看看