• BZOJ2821: 作诗(Poetize)


    2821: 作诗(Poetize)

    Time Limit: 50 Sec  Memory Limit: 128 MB
    Submit: 3300  Solved: 965
    [Submit][Status][Discuss]

    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

    【题解】

    不知是什么原因,我用上次做蒲公英的写法写这道题,T了。。。

    改用陈立杰论文的写法,又T了。。。

    “写这个题以后,我也没干别的,大概三个写法,第一个,就是vector存位置二分它,第二个,就是分块排序二分,第三个,就是预处理每个块中每个数出现次数。如果说还有一点优化,就是加了输出优化,这个对时间秒杀hzw题解意义很重大的,还有取摸优化也是很重要的。很惭愧,就做了一点微小的工作,谢谢大家。” ——姜则岷

    发现蒲公英也可以用这个写法,更快。。

    设块大小为m预处理p[i][j]表示第i块到第j块有多少出现偶数次的,复杂度n^2/m

    预处理pp[i][j]表示第i块,j出现了多少次,然后做前缀和,复杂度m * n(数的个数与n相同)

    查询时,中间块直接获得,两边的数依次枚举,查询pp,根据奇偶分情况讨论,复杂度nm(询问次数与n相同)

    总复杂度m * n + nm + n^2/m,设m = n^x

    2 * n^(x + 1)  + n^(2 - x) <= 4√n^3  当且仅当x + 1 = 2 - x,即x = 0.5时取等号

    m = √n

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6 #include <queue>
      7 #include <vector>
      8 #include <map>
      9 #include <string> 
     10 #include <cmath> 
     11 #include <sstream>
     12 #define min(a, b) ((a) < (b) ? (a) : (b))
     13 #define max(a, b) ((a) > (b) ? (a) : (b))
     14 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
     15 template<class T>
     16 inline void swap(T &a, T &b)
     17 {
     18     T tmp = a;a = b;b = tmp;
     19 }
     20 inline void read(int &x)
     21 {
     22     x = 0;char ch = getchar(), c = ch;
     23     while(ch < '0' || ch > '9') c = ch, ch = getchar();
     24     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
     25     if(c == '-') x = -x;
     26 }
     27 const int INF = 0x3f3f3f3f;
     28 const int MAXN = 100000 + 10;
     29 const int SMAXN = 320;
     30 int size,group,l[SMAXN],r[SMAXN],num[MAXN],n,c[MAXN],m,typ,p[SMAXN][SMAXN],sum[SMAXN][MAXN];
     31 inline int find(int ll, int rr, int x)
     32 {
     33     return sum[rr][x] - sum[ll - 1][x];
     34 }
     35 void make_p()
     36 {
     37     register int i,j,k,ans,now;
     38     for(i = 1;i <= group;++ i)
     39     {
     40         ans = 0, now = i;
     41         for(int j = l[i];j <= r[i];++ j) ++ sum[i][num[j]];
     42         for(int j = l[i];j <= n;++ j)
     43         {
     44             ++ c[num[j]];
     45             if(c[num[j]] != 1) 
     46             {
     47                 if(c[num[j]] & 1) -- ans;
     48                 else ++ ans;
     49             }
     50             if(r[now] == j) p[i][now] = ans, ++ now;
     51         }
     52         for(int j = l[i];j <= n;++ j) c[num[j]] = 0;
     53     }
     54     for(i = 2;i <= group;++ i)
     55         for(int j = 1;j <= typ;++ j)
     56             sum[i][j] += sum[i - 1][j];
     57 }
     58 int query(int ll, int rr)
     59 {
     60     int bl = (ll - 1) / size + 1, br = (rr - 1) / size + 1, ans = 0;
     61     if(bl + 2 <= br)
     62     {
     63         ans = p[bl + 1][br - 1];
     64         for(int i = ll;i <= r[bl];++ i) ++ c[num[i]];
     65         for(int i = l[br];i <= rr;++ i) ++ c[num[i]];
     66         for(int i = ll;i <= r[bl];++ i) 
     67             if(c[num[i]])
     68             {
     69                 int tmp = 0;
     70                 tmp = find(bl + 1, br - 1, num[i]);
     71                 if((tmp & 1) && (c[num[i]] & 1)) ++ ans;
     72                 else if(!tmp && !(c[num[i]] & 1)) ++ ans;
     73                 else if(tmp && !(tmp & 1) && (c[num[i]] & 1)) -- ans; 
     74                 c[num[i]] = 0;
     75             }
     76         for(int i = l[br];i <= rr;++ i) 
     77             if(c[num[i]])
     78             {
     79                 int tmp = 0;
     80                 tmp = find(bl + 1, br - 1, num[i]);
     81                 if((tmp & 1) && (c[num[i]] & 1)) ++ ans;
     82                 else if(!tmp && !(c[num[i]] & 1)) ++ ans;
     83                 else if(tmp && !(tmp & 1) && (c[num[i]] & 1)) -- ans; 
     84                 c[num[i]] = 0;
     85             }
     86     }
     87     else
     88     {
     89         for(int j = ll;j <= rr;++ j)
     90         {
     91             ++ c[num[j]];
     92             if(c[num[j]] == 1) continue;
     93             if(c[num[j]] & 1) -- ans;
     94             else ++ ans;
     95         }
     96         for(int j = ll;j <= rr;++ j) c[num[j]] = 0;
     97     }
     98     return ans;
     99 }
    100 std::ostringstream os;
    101 int main()
    102 {
    103     read(n), read(typ), read(m);
    104     for(register int i = 1;i <= n;++ i) read(num[i]);
    105     int M = 1;for(;(1 << M) <= n;++ M);-- M;
    106     size = sqrt(n);
    107     for(register int i = 1;i <= n;i += size)
    108         l[++ group] = i, r[group] = min(i + size - 1, n);
    109     make_p();
    110     register int pre = 0, l, r;
    111     for(register int i = 1;i <= m;++ i)
    112     {
    113         read(l), read(r);
    114         l = (l + pre), r = (r + pre);
    115         if(l >= n) l -= n;
    116         if(r >= n) r -= n;
    117         l += 1, r += 1;
    118         if(l > r) swap(l, r);
    119         pre = query(l, r);/*printf("%d", pre);putchar('
    ');*/
    120         os << pre << '
    ';
    121     }
    122     std::cout << os.str();
    123     return 0;
    124 }
    BZOJ2821
  • 相关阅读:
    正交矩阵(部分转载)
    向量的点乘和叉乘
    随机森林
    PCA和LDA
    SIFT和SURF特征(草稿)
    12-赵志勇机器学习-Label_Propagation
    11-赵志勇机器学习-DBSCAN聚类
    09-赵志勇机器学习-k-means
    10-赵志勇机器学习-meanshift
    09-numpy-笔记-repeat
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/8403339.html
Copyright © 2020-2023  润新知