zoukankan      html  css  js  c++  java
  • 洛谷 P4135 作诗(分块)

    题目链接

    题意:(n) 个数,每个数都在 ([1,c]) 中,(m) 次询问,每次问在 ([l,r]) 中有多少个数出现偶数次。强制在线。
    (1 leq n,m,c leq 10^5)

    如果不强制在线的话可以想到莫队,关键这个强制在线怎么处理。
    很容易想到对原数列进行根号分块,为了方便表示,定义 (L_i) 为第 (i) 块的左端点,(R_i) 为第 (i) 块的右端点。
    我们记 (t_{i,j}) 表示在 ([L_i,n])(j) 这个数出现了多少次,(f_{i,j}) 表示在 ([L_i,R_j]) 有多少个数出现次数为偶数。
    我还是太 naive 了,一看到这个“区间”就想着用区间 dp 的方式进行转移,复杂度爆炸。
    事实上,我们可以在求出 (t) 的同时求出 (f)。枚举起点块 (i),定义 (num) 记录有多少个数出现了偶数次,一边往后扫一遍更新 (num)

    查询区间 ([l,r]) 的时候,如果 (l,r) 在同一块中,直接暴力查找就行了。
    如果 ([l,r]) 不在同一块中,记 (l')(l) 所在的块,(r')(r) 所在的块,那么我们先将 (ans) 赋值为 (f_{l'+1,r'-1}),然后对于 ([l,R_{l'}] cup [L_{r'},r]) 中所有不同的数 (x),分出以下三种情况:

    1. (x)([L_{l'+1},R_{r'-1}]) 中出现次数为不为零的偶数,但是在 ([l,r]) 中出现次数为奇数,则表明它被算在了 (ans) 中,但实际不符合条件,让 (ans) 减一
    2. (x)([L_{l'+1},R_{r'-1}]) 中出现次数奇数,但是在 ([l,r]) 中出现次数为偶数,则表明它没有被算在了 (ans) 中,但实际符合条件,让 (ans) 加一
    3. (x)([L_{l'+1},R_{r'-1}]) 中没出现过,但是在 ([l,r]) 中出现次数为偶数,让 (ans)(1)
    //Coded by tzc_wk
    /*
    数据不清空,爆零两行泪。
    多测不读完,爆零两行泪。
    边界不特判,爆零两行泪。
    贪心不证明,爆零两行泪。
    D P 顺序错,爆零两行泪。
    大小少等号,爆零两行泪。
    变量不统一,爆零两行泪。
    越界不判断,爆零两行泪。
    调试不注释,爆零两行泪。
    溢出不 l l,爆零两行泪。
    */
    #include <bits/stdc++.h>
    using namespace std;
    #define fi			first
    #define se			second
    #define fz(i,a,b)	for(int i=a;i<=b;i++)
    #define fd(i,a,b)	for(int i=a;i>=b;i--)
    #define foreach(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
    #define all(a)		a.begin(),a.end()
    #define giveup(...) return printf(__VA_ARGS__),0;
    #define fill0(a)	memset(a,0,sizeof(a))
    #define fill1(a)	memset(a,-1,sizeof(a))
    #define fillbig(a)	memset(a,0x3f,sizeof(a))
    #define fillsmall(a) memset(a,0xcf,sizeof(a))
    #define mask(a)		(1ll<<(a))
    #define maskx(a,x)	((a)<<(x))
    #define _bit(a,x)	(((a)>>(x))&1)
    #define _sz(a)		((int)(a).size())
    #define filei(a)	freopen(a,"r",stdin);
    #define fileo(a)	freopen(a,"w",stdout);
    #define fileio(a) 	freopen(a".in","r",stdin);freopen(a".out","w",stdout)
    #define eprintf(...) fprintf(stderr,__VA_ARGS__)
    #define put(x)		putchar(x)
    #define eoln        put('
    ')
    #define space		put(' ')
    #define y1			y_chenxiaoyan_1
    #define y0			y_chenxiaoyan_0
    typedef pair<int,int> pii;
    inline int read(){
    	int x=0,neg=1;char c=getchar();
    	while(!isdigit(c)){
    		if(c=='-')	neg=-1;
    		c=getchar();
    	}
    	while(isdigit(c))	x=x*10+c-'0',c=getchar();
    	return x*neg;
    }
    inline void print(int x){
    	if(x<0){
    		putchar('-');
    		print(abs(x));
    		return;
    	}
    	if(x<=9)	putchar(x+'0');
    	else{
    		print(x/10);
    		putchar(x%10+'0');
    	}
    }
    inline int qpow(int x,int e,int _MOD){
    	int ans=1;
    	while(e){
    		if(e&1)	ans=ans*x%_MOD;
    		x=x*x%_MOD;
    		e>>=1;
    	}
    	return ans;
    }
    const int BLOCK_SZ=320;
    int n=read(),c=read(),m=read(),a[100005],cnt[322][100005],sum[322][322];
    int blk,L[322],R[322],bel[100005];
    int vis[100005];
    inline void prework(){
    	blk=(n-1)/BLOCK_SZ+1;
    	fz(i,1,blk){
    		L[i]=(i-1)*BLOCK_SZ+1;
    		R[i]=min(i*BLOCK_SZ,n);
    		fz(j,L[i],R[i]){
    			bel[j]=i;
    		}
    	}
    	fz(i,1,blk){
    		int num=0;
    		fill0(vis);
    		fz(j,L[i],n){
    			cnt[i][a[j]]++;
    			if(!vis[a[j]])	vis[a[j]]=1,num++;
    			if(cnt[i][a[j]]&1)	num--;
    			else				num++;
    			if(bel[j]!=bel[j+1])	sum[i][bel[j]]=num;
    		}
    	}
    }
    int cntt[100005];
    inline int query(int l,int r){
    	if(bel[l]==bel[r]){
    		int ans=0;
    		fz(i,l,r)	cntt[a[i]]++;
    		fz(i,l,r){
    			if(!vis[a[i]]){
    				if(cntt[a[i]]&1^1)	ans++;
    				vis[a[i]]=1;
    			}
    		}
    		fz(i,l,r)	cntt[a[i]]--,vis[a[i]]=0;
    		return ans;
    	}
    	else{
    		int l0=bel[l],r0=bel[r];
    		fz(i,l,R[l0])	cntt[a[i]]++;
    		fz(i,L[r0],r)	cntt[a[i]]++;
    		int ans=sum[l0+1][r0-1];
    		fz(i,l,R[l0]){
    			if(!vis[a[i]]){
    				if((cnt[l0+1][a[i]]-cnt[r0][a[i]])>0){
    					if(((cntt[a[i]]+cnt[l0+1][a[i]]-cnt[r0][a[i]])&1^1)&&(cnt[l0+1][a[i]]-cnt[r0][a[i]])&1)
    						ans++;
    					if(((cntt[a[i]]+cnt[l0+1][a[i]]-cnt[r0][a[i]])&1)&&(cnt[l0+1][a[i]]-cnt[r0][a[i]])&1^1)
    						ans--;
    				}
    				else{
    					if((cntt[a[i]]&1)^1)	ans++;
    				}
    				vis[a[i]]=1;
    			}
    		}
    		fz(i,L[r0],r){
    			if(!vis[a[i]]){
    				if((cnt[l0+1][a[i]]-cnt[r0][a[i]])>0){
    					if(((cntt[a[i]]+cnt[l0+1][a[i]]-cnt[r0][a[i]])&1^1)&&(cnt[l0+1][a[i]]-cnt[r0][a[i]])&1)
    						ans++;
    					if(((cntt[a[i]]+cnt[l0+1][a[i]]-cnt[r0][a[i]])&1)&&(cnt[l0+1][a[i]]-cnt[r0][a[i]])&1^1)
    						ans--;
    				}
    				else{
    					if(cntt[a[i]]&1^1)	ans++;
    				}
    				vis[a[i]]=1;
    			}
    		}
    		fz(i,l,R[l0])	cntt[a[i]]--,vis[a[i]]=0;
    		fz(i,L[r0],r)	cntt[a[i]]--,vis[a[i]]=0;
    		return ans;
    	}
    }
    signed main(){
    	fz(i,1,n)	a[i]=read();
    	prework();
    	fill0(vis);
    	int anss=0;
    	while(m--){
    		int l=read(),r=read();
    		l=(l+anss)%n+1,r=(r+anss)%n+1;
    		if(l>r)	swap(l,r);
    		anss=query(l,r);
    		cout<<anss<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    [redis] 普通 RedisPool 的 CRUD 实现
    [maven] 常用仓库地址
    [saiku] 通过 saiku 的 DEMO 分析 connection
    [backbone]backbone.js
    [saiku] JCR在saiku中的运用原理
    [redis] 分布式 Redis 的 CRUD 实现
    [redis] session 保存到 redis 简单实现
    [redis] redis 存取键值对常用的三种使用方式
    226. Invert Binary Tree
    225. Implement Stack using Queues
  • 原文地址:https://www.cnblogs.com/ET2006/p/12730542.html
Copyright © 2011-2022 走看看