1. 程式人生 > >名校聯賽第三天A層 問題 C: 與非題解

名校聯賽第三天A層 問題 C: 與非題解

swap pac hid cnblogs stdout str 但是 接下來 出現次數

問題 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: 與非題解