• 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;
    }
    
  • 相关阅读:
    ThinkPHP 3.2 调用自定义函数库
    phpstorm 2017版代码提示功能开启解决方案
    phpstorm 2017激活
    JavaScript返回上一页和返回上一级页面并刷新
    PHP处理Ajax请求与Ajax跨域
    13个能快速开发android的经典项目
    分享6款优秀的 AR/VR 开源库
    Android-----购物车(包含侧滑删除,商品筛选,商品增加和减少,价格计算,店铺分类等)
    Android------视频播放器(包含全屏播放,快退,快进,腾讯新闻的列表播放等)
    吴恩达课后作业学习2-week1-2正则化
  • 原文地址:https://www.cnblogs.com/Yuigahama/p/13519215.html
Copyright © 2020-2023  润新知