码迷,mamicode.com
首页 > 其他好文 > 详细

[loj6500]操作

时间:2021-01-08 11:37:37      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:ret   else   避免   char   偶数   随机   closed   lap   span   

差分,令$b_{i}=a_{i-1}\oplus a_{i}$,对于一个区间$[l,r]$,相当于令$a_{l-1}=a_{r+1}=0$之后求出$b_{l..r+1}$,对区间$[i-k,i)$异或1这个操作可以看作令$b_{i}$和$b_{i-k}$异或1,要求使得$b_{i}$全部为0

这就相当于要求$\forall 0\le i<k$,$b_{l..r+1}$中模$k$余$i$的位置异或为0,对$v_{0..k-1}$随机赋值,那么可以看作判断$\bigoplus_{l\le i\le r+1,i\equiv j(mod\ k)}b_{i}v_{j}=0$,这个可以用前缀和维护(特别的,要特判$b_{l}=a_{l}$和$b_{r+1}=a_{r}$)

判定完无解后,(若有解)考虑如何求最少操作次数:

假设枚举$i$,对于模$k$余$i$且为1的$b_{j}$,将这些$j$记录下来,写作$pos_{1},pos_{2},...,pos_{2m}$(由于有解,必然是偶数个),答案即为$\frac{\sum_{i=1}^{m}pos_{2i}-pos_{2i-1}}{k}$(可以看作一个1不断向后移动,与之后第一个1相消)

对于相邻的模$k$余$i$的位置必然一正一负,通过前缀和(强制最后一个出现的数符号为正)来维护即可(同样要特判$l$和$r+1$),总复杂度为$o(n+m\log_{2}n)$

对于$l$和$r+1$的特判也可以通过$sum_{i,0/1}$表示假设$b_{i}=0/1$时的答案来避免

(另外要特判$k=1$,此时答案即为区间内1的个数)

技术图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 2000005
 4 #define ll long long
 5 int n,t,q,l,r,ans,a[N],b[N],v[N],f[N];
 6 ll g[N],sum[N][2];
 7 char s[N];
 8 int main(){
 9     srand(time(0));
10     scanf("%d%d%d%s",&n,&t,&q,s);
11     for(int i=0;i<n;i++)a[i+1]=s[i]-0;
12     if (t==1){
13         for(int i=1;i<=n;i++)a[i]+=a[i-1];
14         for(int i=1;i<=q;i++){
15             scanf("%d%d",&l,&r);
16             printf("%d\n",a[r]-a[l-1]);
17         }
18         return 0;
19     }
20     for(int i=1;i<=n;i++)b[i]=(a[i-1]^a[i]);
21     for(int i=0;i<t;i++)v[i]=1LL*rand()*rand()%(1<<30);
22     for(int i=1;i<=n;i++)f[i]=(f[i-1]^(b[i]*v[i%t]));
23     for(int i=1;i<=n+1;i++){
24         sum[i][0]=sum[i-1][b[i-1]];
25         sum[i][1]=sum[i-1][b[i-1]]+i-2*g[i%t];
26         if (b[i])g[i%t]=i-g[i%t];
27     }
28     for(int i=1;i<=q;i++){
29         scanf("%d%d",&l,&r);
30         ans=(f[l]^f[r]);
31         if (a[l])ans^=v[l%t];
32         if (a[r])ans^=v[(r+1)%t];
33         if (ans)printf("-1\n");
34         else{
35             if (a[l]!=b[l])printf("%lld\n",(sum[r+1][a[r]]-sum[l][1])/t);
36             else printf("%lld\n",(sum[r+1][a[r]]-sum[l-1][b[l-1]])/t);
37         }
38     }
39     return 0;
40 }
View Code

 

[loj6500]操作

标签:ret   else   避免   char   偶数   随机   closed   lap   span   

原文地址:https://www.cnblogs.com/PYWBKTDA/p/14244989.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!