首页 > 代码库 > 名校联赛第三天A层 问题 C: 与非题解
名校联赛第三天A层 问题 C: 与非题解
问题 C: 与非
时间限制: 2 Sec 内存限制: 256 MB题目描述
作为一名新世纪共产主义的接班人,你认识到了资本主义的软弱性与妥协性,决定全面根除资本主义,跑步迈入共产主义。但是当你即将跨入共产主义大门的时候,遇到了万恶的资本家留下的与非电路封印,经过千辛万苦的研究,你终于把复杂的破解转变成了以下问题:
初始时你有一个空序列,之后有N个操作。
操作分为一下两种:
1 x:在序列末尾插入一个元素x(x=0或1)。
2 L R:定义nand[L,R]为序列第L个元素到第R个元素的与非和,询问nand[L,L]^nand[L,L+1]^nand[L,L+2]^......^nand[L,R]。
Nand就是先与,再非
输入
从文件nand.in中读入数据。
输入第一行一个正整数N,表示操作个数。
接下来N行表示N个操作。
为了体现程序的在线性,记lastans为上一次操作二的回答,初始lastans=0,。对于操作1,你需要对x异或lastans。对于操作二,设现在序列中的元素个数为M,如果lastans=1,那么你需要作如下操作:L=M-L+1,R=M-R+1,swap(L,R)
输出
输出到nand.out中。
输出有多行。为对于每一个操作二的回答。
样例输入
6 1 1 1 1 1 0 2 1 2 2 1 3 2 2 3
样例输出
1 0 0
提示
【数据规模和约定】
N<=4000000 M1<=3900000 M2<=100000
先吐槽一下题目描述,上面的题目是我自己矫正过的,原来题目就卡死了无数人,连样例都搞不出来。
这道题先膜拜一下Troywar大犇,成功通过理性分析与令人窒息的操作强行干过这道题,成功蔑视了数据和出题人的智商。因此我今天就讲一下撸串神的比正解快出去无数倍的“非正解”。
首先,先设定f[i]为nand[1,i],所以f[i]的通项公式就明了了f[i+1]=!(f[i]&a[i+1]),nand[i,i+1]=!(a[i]&a[i+1]),nand[i+2]=!(nand[i+1]&a[i+2]),que[i,j]=a[i]^nand[i+1]^nand[i+2]……
那我们先观察一下f[i+1]和nand[i,i+1],可以发现,若a[i+1]=0那么两式相等,使nand[i+2]=f[i+2],以此类推,可以发现只要有零出现,后方的f[i]一定等于nand[i],一次对于每一次讯问我们只要先暴力找一下第一个为零或直接找f[i]与nand[i]相等的地方就可以,后面f[i]与nand[i]都相等了,因此只要再去维护一个前缀f[i]的异或和即可,找到0后直接将数据分开处理,在0左方直接暴力,在0右方(包括0位),用前缀和搞。
可能很多人会有疑惑,这样不会超时吗,当然不会,首先,通过本题的题目描述可以推断,他一定不是先添加完再询问,应当是添加完一点再去询问几次,这样,由于他的强制在线,出现0的几率是相当大的,因此不会超时,实在担心的话也可以记录一下0的出现次数的前缀和,然后再去二分查找。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #include<map> 7 #include<queue> 8 #include<string> 9 #include<cmath> 10 using namespace std; 11 int n,la,zz; 12 int a[4000005]; 13 int f[4000005]; 14 int sum[4000005]; 15 int nand(int x,int y){ 16 return (!(x&y)); 17 } 18 int na[50]; 19 int su[4000005][2]; 20 int main(){ 21 // freopen("nand.in","r",stdin); 22 // freopen("nand.out","w",stdout); 23 scanf("%d",&n); 24 for(int i=1;i<=n;i++) 25 { 26 int z; 27 scanf("%d",&z); 28 if(z==1) 29 { 30 int x; 31 scanf("%d",&x); 32 x^=la; 33 zz++; 34 a[zz]=x; 35 36 f[zz]=nand(f[zz-1],a[zz]); 37 sum[zz]=sum[zz-1]^f[zz]; 38 39 su[zz][0]=su[zz-1][0]; 40 su[zz][1]=su[zz-1][1]; 41 42 su[zz][x]++; 43 } 44 else 45 { 46 int x,y; 47 scanf("%d%d",&x,&y); 48 if(la) 49 { 50 x=zz-x+1; 51 y=zz-y+1; 52 swap(x,y); 53 } 54 int cnt=a[x],bj=0,sm=a[x]; 55 for(int i=x+1;i<=y;i++) 56 { 57 sm=nand(sm,a[i]); 58 if(sm==f[i]) 59 { 60 bj=i; 61 break; 62 } 63 cnt^=sm; 64 } 65 if(bj) cnt^=sum[y]^sum[bj-1]; 66 la=cnt; 67 printf("%d\n",la); 68 } 69 } 70 // while(1); 71 return 0; 72 }
名校联赛第三天A层 问题 C: 与非题解