zoukankan      html  css  js  c++  java
  • [bzoj] 2821 作诗(Poetize) || 分块

    原题

    求[l,r]中有多少个数出现过正偶数次


    分块板子题。
    预处理cnt[i][j]和f[i][j],cnt[i][j]记录i在前j块出现的次数,f[i][j]表示i块到j块的答案。
    每次询问,整块的给出答案后,暴力非整块,对于非整块的答案有三种特判来判断是否答案++:
    1、整块中没出现,非整块出现偶数次,则++
    2、整块出现偶数次,非整块出现奇数次,则--
    3、整块出现奇数次,非整块出现奇数次,则++

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define N 100010
    #define B 319
    #define inf 0x3f3f3f3f
    using namespace std;
    int n,m,num,s,l,r,ans,a[N],sum[N],idx;
    int bl[B],br[B],f[B][B],cnt[N][B];
    bool v[N];
    
    int read()
    {
        int ans=0,fu=1;
        char j=getchar();
        for (;j<'0' || j>'9';j=getchar()) if (j=='-') fu=-1;
        for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
        return ans*fu;
    }
    
    void init()
    {
        int k,t,h,c,ans=0;
        for (int i=1;i<=s;i++)
        {
    	ans=0;
    	k=bl[i];
    	for (int j=k;j<n;j++)
    	    sum[a[j]]=0;
    	for (int j=i;j<=s;j++)
    	{
    	    t=br[j];
    	    while (k<=t)
    	    {
    		c=++sum[a[k]];
    		if (c%2) ans--;
    		else ans++;
    		++k;
    	    }
    	    f[i][j]=ans;
    	}
        }
        memset(sum,0,sizeof(sum));
        for (int i=1;i<=s;i++)
        {
    	for (int j=0;j<idx;j++) cnt[j][i]=cnt[j][i-1];
    	h=bl[i];
    	t=br[i];
    	while (h<=t) cnt[a[h]][i]=++sum[a[h]],++h;
        }
    }
    
    int query(int l,int r)
    {
        int ret=0,c;
        if (r-l<2*s)
        {
    	for (int i=l;i<=r;i++)
    	    if (!v[a[i]]) v[a[i]]=1,sum[a[i]]=1;
    	    else ++sum[a[i]];
    	for (int i=l;i<=r;i++)
    	    if (v[a[i]])
    	    {
    		if (sum[a[i]]%2==0) ret++;
    		v[a[i]]=0;
    	    }
    	return ret;
        }
        int L=l/num+1,R=r/num+1,st,en;
        if (l==bl[L]) --L;
        if (r==br[R]) ++R;
        en=br[L];st=bl[R];
        for (int i=l;i<=en;i++)
    	if (!v[a[i]]) v[a[i]]=1,sum[a[i]]=1;
    	else ++sum[a[i]];
        for (int i=st;i<=r;i++)
    	if (!v[a[i]]) v[a[i]]=1,sum[a[i]]=1;
    	else ++sum[a[i]];
        for (int i=1;i<=idx;i++)
    	if (!v[i] && (cnt[i][R-1]-cnt[i][L])%2==0) ret++;
        for (int i=l;i<=en;i++)
    	if (v[a[i]])
    	{
    	    c=cnt[a[i]][R-1]-cnt[a[i]][L];
    	    c+=sum[a[i]];
    	    if (c%2==0) ret++;
    	    v[a[i]]=0;
    	}
        for (int i=st;i<=r;i++)
           if (v[a[i]])
    	{
    	    c=cnt[a[i]][R-1]-cnt[a[i]][L];
    	    c+=sum[a[i]];
    	    if (c%2==0) ret++;
    	    v[a[i]]=0;
    	}
        return ret;
    }
    
    int main()
    {
        n=read();
        idx=read();
        m=read();
        for (int i=0;i<n;i++) a[i]=read();
        num=sqrt(n);
        for (int i=0;i<n;i++)
    	if (i%num==0) br[s]=i-1,bl[++s]=i;
        br[s]=n-1;
        bl[s+1]=br[s+1]=n;
        init();
        while (m--)
        {
    	l=read();r=read();
    	l=(l+ans)%n;
    	r=(r+ans)%n;
    	if (l>r) swap(l,r);
    	printf("%d
    ",ans=query(l,r));
        }
        return 0;
    }
    
  • 相关阅读:
    Extjs的学习及MIS系统实践应用(系列文章)
    Extjs的js函数
    【VS Code】使用技巧
    【算法技巧】算法技巧记录
    【踩坑记录】vs2017 git 版本控制问题
    【IDE】解决国内下载安装vs 过慢问题
    【c#基础】.Net编译器平台
    【查看IIS站点日志】
    【项目管理】人月神话
    【c#基础】反射、元数据和动态编程
  • 原文地址:https://www.cnblogs.com/mrha/p/8185426.html
Copyright © 2011-2022 走看看