首页 > 代码库 > 名校联赛第三天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 }
View Code

 

名校联赛第三天A层 问题 C: 与非题解