NOIp2018集訓test-10-19 (bike day5)
Bike老爺問了好幾天到底要怎樣簡單的題目你們才能AK啊終於在他每天降難度直到要走了才出了一套我們能AK的題。雖然前幾天的題換成llj肯定隨便AK。
其實最近有點方雖然通常最後都寫完了把該拿的分拿了該拍的拍了,但是並不是很順利的那種前30min切了T1,再1h切t2拍了最後寫t3然後拍這樣,這套題推了半天t1沒推出來就棄了去搞t2,結果半天把fwt打掛了又去搞t3,開考1h多終於把t3搞出來了才又去回想我的fwt,最後1h先猜了個t1的結論然後先想打個樹dp之類的驗證發現不會,又證了半天才勉強覺得是對的。t3還沒有拍,交題的時候都很虛。如果是正式的考場,特別是像noip比較簡單的,這種情況我可能心態就崩了,別說AK,一不小心爆個0也不是不可能。但總得來說先通讀題每道有個大概的想法和及時棄題不要對著一個狂肝其他該要的分都不要(去年能要是明白這個道理我大概就不在這裡了吧)應該是沒錯的,然後心態要穩這樣?
B 君的第一題hohhot
結論題。畫一條鏈,發現勝負只跟最上面一條邊有關,畫一朵菊花,發現答案就是和根相連的所有邊的異或和。大膽地猜測,這是個結論。考慮和根相連只有一條邊的情況,任何一次操作都會改變這條邊,那麼勝負只跟這條邊原本的狀態有關。如果根有多條邊相連,那麼每條邊底下的操作情況互不影響,答案就是每條邊的答案的異或和。
1 //Achen
2 #include<bits/stdc++.h>
3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
5 #define Formylove return 0
6 const int N=100007;
7 typedef long long LL;
8 typedef double db;
9 using namespace std;
10 int n,a[N];
11
12 template<typename T> void read(T &x) {
13 char ch=getchar(); x=0; T f=1;
14 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
15 if (ch=='-') f=-1,ch=getchar();
16 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
17 }
18
19 #define ANS
20 int main() {
21 #ifdef ANS
22 freopen("hohhot.in","r",stdin);
23 freopen("hohhot.out","w",stdout);
24 #endif
25 read(n);
26 For(i,2,n) {
27 int x,y,z;
28 read(x); read(y); read(z);
29 a[x]^=z; a[y]^=z;
30 }
31 For(i,1,n) printf("%d\n",a[i]);
32 Formylove;
33 }
View Code
B 君的第二題lhasa
這不是一道FWT的裸題麼,畢老爺給的標答也就是換一種方式的各種集合變換,和FWT也差不到哪去吧,我覺得noip不會考。。
1 //Achen
2 #include<bits/stdc++.h>
3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
5 #define Formylove return 0
6 const int N=1048599;
7 typedef long long LL;
8 typedef double db;
9 using namespace std;
10 int n,k,a[N];
11
12 template<typename T> void read(T &x) {
13 char ch=getchar(); x=0; T f=1;
14 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
15 if(ch=='-') f=-1,ch=getchar();
16 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
17 }
18
19 LL f[N],b[N];
20 void FWT(int n,int F) {
21 for(int i=1;i<n;i<<=1)
22 for(int j=0,pp=(i<<1);j<n;j+=(pp))
23 for(int k=0;k<i;k++) {
24 LL x=f[j+k],y=f[j+k+i];
25 if(F==1) f[j+k+i]=x+y;
26 else f[j+k+i]=y-x;
27 }
28
29 }
30
31 #define ANS
32 int main() {
33 #ifdef ANS
34 freopen("lhasa.in","r",stdin);
35 freopen("lhasa.out","w",stdout);
36 #endif
37 read(n); read(k);
38 For(i,1,n) {
39 read(a[i]);
40 f[a[i]]++;
41 }
42 int up=(1<<k);
43 For(i,0,up) b[i]=f[i];
44 FWT(up,1);
45 For(i,0,up) f[i]=f[i]*f[i];
46 FWT(up,-1);
47 For(i,0,up) f[i]=(f[i]-b[i])/2;
48 //For(i,0,up-1) printf("%lld ",f[i]); puts("");
49 For(i,0,k-1) {
50 Rep(s,up-1,0) if(!(s&(1<<i)))
51 f[s]+=f[s|(1<<i)];
52 }
53 For(s,0,up-1) printf("%lld\n",f[s]);
54 Formylove;
55 }
View Code
B 君的第三題urumqi
並查集+set啟發式合併,之前講過的一道題。
我開了兩個並查集,一個並查集維護和我相同集合的元素,一個並查集維護每個集合不能有的元素。每個集合的每個並查集開個set。
合併的時候啟發式合併,不等關秀就在每個集合不能有的元素的set裡放進一個對面集合的代表元。相等關係我處理的比較暴力,不管怎麼樣先合併(啟發式)再說,合併到一半發現衝突就把這部分合並都撤銷了輸出NO否則最終合併完輸出YES,因為有撤銷操作所以大概要用multiset。
1 //Achen
2 #include<bits/stdc++.h>
3 #define For(i,a,b) for(int i=(a);i<=(b);i++)
4 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
5 #define Formylove return 0
6 const int N=200007;
7 typedef long long LL;
8 typedef double db;
9 using namespace std;
10 int n,sz,x[N],y[N],o[N],ls[N];
11 int sta[N],top,sta2[N],top2;
12 int fa[2][N];
13 multiset<int>s1[N],s2[N];
14
15 template<typename T> void read(T &x) {
16 char ch=getchar(); x=0; T f=1;
17 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
18 if(ch=='-') f=-1,ch=getchar();
19 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
20 }
21
22 int find(int x,int f) { return x==fa[f][x]?x:fa[f][x]=find(fa[f][x],f); }
23
24 #define ANS
25 int main() {
26 #ifdef ANS
27 freopen("urumqi.in","r",stdin);
28 freopen("urumqi.out","w",stdout);
29 #endif
30 read(n);
31 For(i,1,n) {
32 read(x[i]); read(y[i]); read(o[i]);
33 ls[++ls[0]]=x[i];
34 ls[++ls[0]]=y[i];
35 }
36 sort(ls+1,ls+ls[0]+1);
37 sz=unique(ls+1,ls+ls[0]+1)-(ls+1);
38 For(i,1,n) {
39 x[i]=lower_bound(ls+1,ls+sz+1,x[i])-ls;
40 y[i]=lower_bound(ls+1,ls+sz+1,y[i])-ls;
41 }
42 For(i,1,sz) {
43 fa[0][i]=i;
44 fa[1][i]=i;
45 s1[i].insert(i);
46 }
47 For(i,1,n) {
48 int u1=find(x[i],1),v1=find(x[i],0);
49 int u2=find(y[i],1),v2=find(y[i],0);
50 if(o[i]) {
51 if(u1==u2) puts("Yes");
52 else {
53 int fl=0;
54 if(s1[u1].size()<s1[u2].size()) swap(u1,u2),swap(v1,v2);
55 fa[1][u2]=u1;
56 top=0;
57 while(s1[u2].size()) {
58 int tp=*s1[u2].begin();
59 if(s2[v1].find(tp)!=s2[v1].end()) {
60 while(top) {
61 int t=sta[top--];
62 s1[u2].insert(t);
63 s1[u1].erase(t);
64 }
65 fl=1;
66 break;
67 }
68 s1[u2].erase(s1[u2].begin());
69 sta[++top]=tp;
70 s1[u1].insert(tp);
71 }
72 if(!fl) {
73 int tpfl=0;
74 if(s2[v1].size()<s2[v2].size()) { tpfl=1; swap(u1,u2),swap(v1,v2); }
75 fa[0][v2]=v1;
76 top2=0;
77 while(s2[v2].size()) {
78 int tp=*s2[v2].begin();
79 if(s1[u1].find(tp)!=s1[u1].end()) {
80 while(top) {
81 int t=sta[top--];
82 if(!tpfl) {
83 s1[u2].insert(t);
84 s1[u1].erase(t);
85 }
86 else {
87 s1[u1].insert(t);
88 s1[u2].erase(t);
89 }
90 }
91 while(top2) {
92 int t=sta2[top2--];
93 s2[v2].insert(t);
94 s2[v1].erase(s2[v1].find(t));
95 }
96 }
97 s2[v2].erase(s2[v2].begin());
98 sta2[++top2]=tp;
99 s2[v1].insert(tp);
100 }
101 }
102 if(fl) {
103 puts("No");
104 fa[1][u1]=u1; fa[1][u2]=u2;
105 fa[0][v1]=v1; fa[0][v2]=v2;
106 }
107 else puts("Yes");
108 }
109 }
110 else {
111 if(u1==u2) puts("No");
112 else {
113 puts("Yes");
114 s2[v1].insert(u2);
115 s2[v2].insert(u1);
116 }
117 }
118 }
119 Formylove;
120 }
View Code