zoukankan      html  css  js  c++  java
  • 【BZOJ2821】作诗(Poetize) 分块

    Description

    神犇SJY虐完HEOI之后给傻×LYD出了一题:
    SHY是T国的公主,平时的一大爱好是作诗。
    由于时间紧迫,SHY作完诗之后还要虐OI,于是SHY找来一篇长度为N的文章,阅读M次,每次只阅读其中连续的一段[l,r],从这一段中选出一些汉字构成诗。因为SHY喜欢对偶,所以SHY规定最后选出的每个汉字都必须在[l,r]里出现了正偶数次。而且SHY认为选出的汉字的种类数(两个一样的汉字称为同一种)越多越好(为了拿到更多的素材!)。于是SHY请LYD安排选法。
    LYD这种傻×当然不会了,于是向你请教……
    问题简述:N个数,M组询问,每次问[l,r]中有多少个数出现正偶数次。

    Input

    输入第一行三个整数n、c以及m。表示文章字数、汉字的种类数、要选择M次。
    第二行有n个整数,每个数Ai在[1, c]间,代表一个编码为Ai的汉字。
    接下来m行每行两个整数l和r,设上一个询问的答案为ans(第一个询问时ans=0),令L=(l+ans)mod n+1, R=(r+ans)mod n+1,若L>R,交换L和R,则本次询问为[L,R]。

    Output

    输出共m行,每行一个整数,第i个数表示SHY第i次能选出的汉字的最多种类数。

    Sample Input

    5 3 5
    1 2 2 3 1
    0 4
    1 2
    2 2
    2 3
    3 5

    Sample Output

    2
    0
    0
    0
    1

    HINT

    对于100%的数据,1<=n,c,m<=10^5

    Source

      还没AC就写题解2333,原因是因为入BZ坑以来第二次遇到卡评测的事辣,虽然没法评测,遇到这种事莫名感兴趣XD。
      比较神的分块辣,比之前做的麻烦多了,一开始感觉弹飞绵羊思路挺有趣,一看这道题,强制在线,10^5,smg,看题解,脑冻好大啊,我自己肯定想不出,首先我们需要预处理出两个东西。
      1.f[i][j]:第i块到第j块中合法的个数。
      2.前缀和[i][j]:前i个汉字中j出现的个数,当然并不是用2维数组的来实现的,而是在结构体中以汉字为第一关键字,以所在序号为第二关键字排序,用的时候二分即可。
      这样,题目变得很明了了,查询时,对于同块或相邻块内的查询,直接暴力二分统计即可,若不在同一个块内,则开始直接ans=f[pos[l]+1][pos[r]-1](pos[]为所在块),也就是吧l,r之间的完整的块直接用f[][],剩下的暴力二分,注意细节。
      但是!!!跟着黄学长写,分成sqrt(n)块的我t了,要分成sqrt(n/logn)块,不知道哪里写残了,一定要写个分成sqrt(n)的版本出来。
      
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <algorithm> 
      6 #define N 100010
      7 #define sN 1555
      8 #define inf 0x7fffffff
      9 using namespace std;
     10 struct data{int v,p;}b[N]; 
     11 int f[sN][sN],first[N],last[N],flag[N],temp[N],a[N],pos[N],L[sN],R[sN];
     12 int n,m,block,cnt,c;
     13 bool cmp(data a,data b) {if (a.v<b.v) return 1; else if (a.v==b.v && a.p<b.p) return 1; return 0;}
     14 inline int read()
     15 {
     16     char c;
     17     int ans=0;
     18     while ((c=getchar())==' ' || c=='
    ' || c=='
    ');
     19     ans=c-'0';
     20     while (isdigit(c=getchar())) ans=ans*10+c-'0';
     21     return ans;
     22 }
     23 void part1_pre()
     24 {
     25     for (int i=1;i<=cnt;i++)
     26     {
     27         int tot;
     28         for (int j=L[i];j<=n;j++) temp[a[j]]=0;
     29         tot=0;
     30         for (int j=L[i];j<=n;j++)
     31         {
     32             if (!(temp[a[j]]&1) && temp[a[j]]) tot--;
     33             temp[a[j]]++;
     34             if (!(temp[a[j]]&1)) tot++;
     35             f[i][pos[j]]=tot;
     36         }
     37     }
     38     for (int i=1;i<=n;i++)
     39     {
     40         b[i].v=a[i];
     41         b[i].p=i;
     42     }
     43     sort(b+1,b+n+1,cmp);
     44     for (int i=1;i<=n;i++)
     45     {
     46         if (!first[b[i].v]) first[b[i].v]=i;
     47         last[b[i].v]=i;
     48     }
     49 }
     50 int findup(int x,int v)
     51 {
     52     int tem=0,l=first[v],r=last[v];
     53     while (l<=r)
     54     {
     55         int mid=(l+r)>>1;
     56         if (x<b[mid].p) r=mid-1;
     57         else {l=mid+1;tem=mid;}
     58     }
     59     return tem;
     60 }
     61 int finddown(int x,int v)
     62 {
     63     int tem=inf,l=first[v],r=last[v];
     64     while (l<=r)
     65     {
     66         int mid=(l+r)>>1;
     67         if (x>b[mid].p) l=mid+1;
     68         else {r=mid-1;tem=mid;}
     69     }
     70     return tem;
     71 }
     72 int find(int x,int y,int v) {return max(findup(y,v)-finddown(x,v)+1,0);}
     73 int query(int x,int y)
     74 {
     75     int ans=0,t,t1;
     76     if (pos[x]==pos[y] || pos[x]+1==pos[y])
     77     {
     78         for (int i=x;i<=y;i++)
     79         {
     80             if (!flag[a[i]])
     81             {
     82                 t=find(x,y,a[i]);
     83                 if (!(t&1)) {ans++;flag[a[i]]=1;}
     84             }
     85         }
     86         for (int i=x;i<=y;i++) flag[a[i]]=0;
     87     }
     88     else
     89     {
     90         int l=L[pos[x]+1],r=R[pos[y]-1];
     91         ans=f[pos[x]+1][pos[y]-1];
     92         for (int i=x;i<l;i++)
     93         {
     94             if (!flag[a[i]])
     95             {
     96                 flag[a[i]]=1;
     97                 t=find(x,y,a[i]);t1=find(l,r,a[i]);
     98                 if (!(t&1)) 
     99                     {if ((t1&1) || !t1) ans++;}
    100                 else   
    101                     if (!(t1&1) && t1) ans--;
    102             }
    103         }
    104         for (int i=r+1;i<=y;i++)
    105         {
    106             if (!flag[a[i]])
    107             {
    108                 flag[a[i]]=1;
    109                 t=find(x,y,a[i]);t1=find(l,r,a[i]);
    110                 if (!(t&1)) 
    111                     {if ((t1&1) || !t1) ans++;}
    112                 else
    113                     if (!(t1&1) && t1) ans--;
    114             }
    115         }
    116         for (int i=x;i<l;i++) flag[a[i]]=0;
    117         for (int i=r+1;i<=y;i++) flag[a[i]]=0;
    118     }
    119     return ans;
    120 }
    121 int main()
    122 {
    123     int ans=0;
    124     n=read();c=read();m=read();
    125     block=sqrt((double)n/log((double)n)*log(2));
    126     for (int i=1;i<=n;i++) a[i]=read();
    127     if (n%block) cnt=n/block+1;
    128     else cnt=n/block;
    129     for (int i=1;i<=n;i++) pos[i]=(i-1)/block+1;
    130     for(int i=1;i<=cnt;i++)
    131     L[i]=(i-1)*block+1,R[i]=i*block;
    132     R[cnt]=n;
    133     part1_pre();
    134     for (int i=1;i<=m;i++)
    135     {
    136          
    137         int l=read(),r=read();
    138         int x=(l+ans)%n+1,y=(r+ans)%n+1;
    139         if (x>y) swap(x,y);
    140         ans=query(x,y);
    141         printf("%d
    ",ans);
    142     }
    143     return 0;
    144 }
    sqrt(n/logn)版本
    —Anime Otaku Save The World.
  • 相关阅读:
    CentOS8下安装mysql8
    Git使用
    《操作系统导论》读书笔记
    《Linux命令行大全》读书笔记
    Centos8 开机后显示 Activate the web console with: systemctl enable --now cockpit.socke
    numpy学习笔记
    CentOS8使用阿里源
    Python 面向对象
    matplotlib解决不显示中文问题
    MySQL基础第三课
  • 原文地址:https://www.cnblogs.com/DMoon/p/5270264.html
Copyright © 2011-2022 走看看