zoukankan      html  css  js  c++  java
  • [BZOJ2821]作诗(分块)

    题意

    N个数,M组询问,每次问[l,r]中有多少个数出现正偶数次
    对于100%的数据,1≤n,c,m≤105

    题解

    (传说lyd省选的时候看错题   把题看成这个了   从此又多了一道分块神题)
    把N个数分成sqrt(n)块,预处理d[i][j]表示第i块起点到第j块末尾的答案  枚举起点i,并维护一个数组记录每个数到目前为止出现的次数,从偶变奇、从奇变偶时相应增减答案。  把每个数在数列中出现的位置从小到大排序后放入到一个数组Arr中备用。  读入每个询问[l,r]。如果l和r在同一个块中暴力即可,否则设l所在块的末尾为l’,r所在块的起点为r’,[l’+1,r’-1]的答案已经预处理出。扫描l~l’, r’~r的所有数,统计每个数出现的次数cnt,第一次出现时把它加入队列。  对于队列中的每个数,在数组Arr中二分l’+1和r’-1,得到在[l’+1,r’-1]中出现的次数k。通过对k和当前队列中的数的cnt进行奇偶性讨论更新答案

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<cmath>
      5 #include<algorithm>
      6 #include<vector>
      7 using namespace std;
      8 const int N=100100;
      9 vector<int> vec[N];
     10 int n,c,m,a[N],block[N],Block,R[1600],L[1600],cnt[N],f[1600][1600],ans,stack[N],top;
     11 inline int read(){
     12     int f=1;int x=0;char ch=getchar();
     13     while(ch<'0'||ch>'9'){
     14         if(ch=='-')f=-1;
     15         ch=getchar();
     16     }
     17     while(ch>='0'&&ch<='9'){
     18         x=(x<<3)+(x<<1)+ch-'0';
     19         ch=getchar();
     20     }
     21     return x*f;
     22 }
     23 int find1(int x,int y){
     24     int l=0;int r=vec[x].size()-1;
     25     int tmp=-99999;
     26     while(l<=r){
     27         int mid=(l+r)>>1;
     28         if(vec[x][mid]<=y){
     29             tmp=mid;
     30             l=mid+1;
     31         }
     32         else r=mid-1;
     33     }
     34     return tmp;
     35 }
     36 int find2(int x,int y){
     37     int l=0;int r=vec[x].size()-1;
     38     int tmp=9999;
     39     while(l<=r){
     40         int mid=(l+r)>>1;
     41         if(vec[x][mid]>=y){
     42             tmp=mid;
     43             r=mid-1;
     44         }
     45         else l=mid+1;
     46     }
     47     return tmp;
     48 }
     49 int main(){
     50     n=read();c=read();m=read();
     51     Block=sqrt(n);
     52     for(int i=1;i<=n;i++){
     53         a[i]=read();
     54         vec[a[i]].push_back(i);
     55         block[i]=(i-1)/Block+1;
     56         if(!L[block[i]])L[block[i]]=i;
     57         R[block[i]]=i;
     58     }
     59     for(int i=1;i<=block[n];i++){    
     60         int tot=0;
     61         for(int j=L[i];j<=n;j++){
     62             if(!(cnt[a[j]]&1)&&cnt[a[j]])tot--;
     63             cnt[a[j]]++;
     64             if(!(cnt[a[j]]&1))tot++;
     65             f[i][block[j]]=tot;
     66         } 
     67         for(int j=L[i];j<=n;j++){
     68             cnt[a[j]]=0;
     69         }
     70     }
     71     while(m--){
     72         int l,r;
     73         l=read();r=read();
     74         l=(l+ans)%n+1;r=(r+ans)%n+1;
     75         if(l>r)swap(l,r);
     76         if(block[l]+1>=block[r]){
     77             ans=0;
     78             for(int i=l;i<=r;i++){
     79                 cnt[a[i]]++;
     80                 if(cnt[a[i]]==1)continue;
     81                 if(cnt[a[i]]&1)ans--;
     82                 else ans++;
     83             } 
     84             for(int i=l;i<=r;i++)
     85                 cnt[a[i]]=0;
     86         } 
     87         else{
     88             ans=f[block[l]+1][block[r]-1];
     89             top=0;
     90             for(int i=l;i<=R[block[l]];i++){
     91                 cnt[a[i]]++;
     92                 if(cnt[a[i]]==1)stack[++top]=a[i];
     93             } 
     94             for(int i=L[block[r]];i<=r;i++){
     95                 cnt[a[i]]++;
     96                 if(cnt[a[i]]==1)stack[++top]=a[i];
     97             } 
     98             while(top){
     99                 int z=stack[top--];
    100                 int tmp=max(find1(z,L[block[r]]-1)-find2(z,R[block[l]]+1)+1,0);
    101                 if(tmp==0){
    102                     if(cnt[z]%2==0)ans++; 
    103                 }
    104                 else{
    105                     if(tmp&1){if(cnt[z]&1)ans++;}
    106                     else {if(cnt[z]&1)ans--;}
    107                 }
    108                 cnt[z]=0;
    109             }
    110         }
    111         printf("%d
    ",ans);
    112     }
    113     return 0;
    114 } 
  • 相关阅读:
    MYSQL学习(二)
    Nginx学习总结(一)
    关于微服务架构的个人理解(一)
    深入理解Java虚拟机(二) : 垃圾回收
    深入理解Java虚拟机(一) 运行时数据区划分
    多线程系列之 线程安全
    多线程系列之 java多线程的个人理解(二)
    多线程系列之 Java多线程的个人理解(一)
    Java基础04—字符串
    Java基础03—流程控制
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9477703.html
Copyright © 2011-2022 走看看