zoukankan      html  css  js  c++  java
  • [cf1083F]The Fair Nut and Amusing Xor

    令$c_{i}=a_{i}oplus b_{i}$,那么也就是要对$c_{i}$执行操作使其变为0

    显然有一个贪心的策略,即从左往右,若当前$c_{i} e 0$,则执行对$[i,i+k)$异或$c_{i}$的操作,若$i+kge n+2$则说明无解

    更具体的,定义$p_{i}$为到第$i$个位置上时第$i$个位置上的操作,那么有$p_{i}=p_{i-k}oplus c_{i-1}oplus c_{i}$(特别的,$c_{0}=0$,若$ile 0$则$p_{i}=0$)

    解释一下,除去$p_{i-k}$以外,当前所有操作都是$i-1$和$i$一起执行,不难发现这些操作的总影响是$p_{i-k}oplus c_{i-1}$,初始是$c_{i}$,再异或一下即为当前的值

    我们所求的即为$p_{i}$中非0的个数以及判定$p_{i}$($ige n-k+2$)是否存在非0数(即无解)

    令$c'_{i}=c_{i}oplus c_{i-1}$,记第$i$组为模$k$余$i$的$j$($1le jle n$)的$c'_{j}$所构成的序列($0le i<k$,不改变相对顺序),每一组显然独立,且对于第$i$组,需要以下两个信息:

    1.所有数异或的结果,若存在$i otequiv n-k+1(mod k)$且结果不为0,则无解

    2.前缀异或和中非0数的个数,这个即为答案

    对于第一个修改可以很容易支持(维护0的个数),对于第二个直接记录前缀异或和,那么修改即支持后缀异或的操作以及统计非0的个数,也就是全部减去0的个数

    再对每一组内部分块,设块大小为$K$,对于每一个块维护桶以及修改懒标记,考虑复杂度:

    时间复杂度为$o((frac{n}{K}+K)q)$,取$K=sqrt{n}$即为$o(qsqrt{n})$

    空间复杂度为$o(frac{2^{14}n}{K})$,在最优时间复杂度的取值下可以接受

    另外还有一个特殊情况,当$k$较大时每一个块的大小无法达到$K$(如$k=n$时空间会退化为$o(2^{14}n)$),更具体的,当$k>sqrt{n}$,对每一个块暴力处理,复杂度为$o(frac{n}{k}q)$,与之前相同

    其他情况下,即使每一组恰好多出一个大小为1的块,也就至多多$sqrt{n}$个块,并没有太大影响

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 200005
     4 #define NN 1005
     5 int n,k,q,K,x,y,sp,flag,ans_sum,a[N],b[N],cc[N],c[N],len[N],check[N],ans[N];
     6 int bl[N],id[NN][NN],tag[N],tot[NN][(1<<14)];
     7 char s[11];
     8 void add(int k){
     9     if (k!=sp)flag+=(check[k]>0);
    10     ans_sum+=ans[k];
    11 }
    12 void del(int k){
    13     if (k!=sp)flag-=(check[k]>0);
    14     ans_sum-=ans[k];
    15 }
    16 void add(int x,int i){
    17     tot[id[x][i/K]][c[i*k+x]]++;
    18     if (c[i*k+x]==tag[id[x][i/K]])ans[x]++;
    19 }
    20 void del(int x,int i){
    21     tot[id[x][i/K]][c[i*k+x]]--;
    22     if (c[i*k+x]==tag[id[x][i/K]])ans[x]--;
    23 }
    24 void update(int x,int y){
    25     del(bl[x]);
    26     check[bl[x]]^=y;
    27     int i=(x-bl[x])/k;
    28     if (k>K){
    29         for(;i<len[bl[x]];i++){
    30             if (!c[i*k+bl[x]])ans[bl[x]]--;
    31             c[i*k+bl[x]]^=y;
    32             if (!c[i*k+bl[x]])ans[bl[x]]++;
    33         }
    34     }
    35     else{
    36         for(;(i<len[bl[x]])&&(i%K);i++){
    37             del(bl[x],i);
    38             c[i*k+bl[x]]^=y;
    39             add(bl[x],i);
    40         }
    41         if (i!=len[bl[x]]){
    42             for(;i<len[bl[x]];i+=K){
    43                 ans[bl[x]]-=tot[id[bl[x]][i/K]][tag[id[bl[x]][i/K]]];
    44                 tag[id[bl[x]][i/K]]^=y;
    45                 ans[bl[x]]+=tot[id[bl[x]][i/K]][tag[id[bl[x]][i/K]]];
    46             }
    47         }
    48     }
    49     add(bl[x]);
    50 }
    51 void write(){
    52     if (flag)printf("-1
    ");
    53     else printf("%d
    ",n-ans_sum);
    54 }
    55 int main(){
    56     scanf("%d%d%d",&n,&k,&q);
    57     K=(int)sqrt(n);
    58     for(int i=0;i<n;i++)scanf("%d",&a[i]);
    59     for(int i=0;i<n;i++)scanf("%d",&b[i]);
    60     sp=n%k;
    61     for(int i=0;i<n;i++){
    62         bl[i]=i%k;
    63         len[bl[i]]++;
    64         cc[i]=(a[i]^b[i]);
    65     }
    66     c[0]=cc[0];
    67     for(int i=1;i<n;i++)c[i]=(cc[i-1]^cc[i]);
    68     for(int i=k;i<n;i++)c[i]=(c[i]^c[i-k]);
    69     for(int i=n-k;i<n;i++)check[bl[i]]=c[i];
    70     if (k>K){
    71         for(int i=0;i<n;i++)ans[bl[i]]+=(c[i]==0);
    72     }
    73     else{
    74         int V=0;
    75         for(int i=0;i<k;i++)
    76             for(int j=0;j<len[i];j+=K)id[i][j/K]=++V;
    77         for(int i=0;i<n;i++)add(bl[i],(i-bl[i])/k);
    78     }
    79     for(int i=0;i<k;i++)add(i);
    80     write();
    81     for(int i=1;i<=q;i++){
    82         scanf("%s%d%d",s,&x,&y);
    83         x--;
    84         if (s[0]=='a'){
    85             update(x,(a[x]^y));
    86             if (x<n-1)update(x+1,(a[x]^y));
    87             a[x]=y;
    88         }
    89         else{
    90             update(x,(b[x]^y));
    91             if (x<n-1)update(x+1,(b[x]^y));
    92             b[x]=y;
    93         }
    94         write();
    95     }
    96 }
    View Code
  • 相关阅读:
    ubuntu安装iscsi
    函数模板的trick
    EF-Code First(5):二级缓存
    了解线程的属性及方法
    算法--中位数计算
    实习面试
    长轮询实现Chat并迁移到Azure测试
    非聚集索引及其性能优化
    架构设计方案
    大话数据结构-图
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14428401.html
Copyright © 2011-2022 走看看