日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ3510 首都

發(fā)布時間:2023/12/20 编程问答 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ3510 首都 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題目描述

在X星球上有N個國家,每個國家占據(jù)著X星球的一座城市。由于國家之間是敵對關(guān)系,所以不同國家的兩個城市是不會有公路相連的。?
X星球上戰(zhàn)亂頻發(fā),如果A國打敗了B國,那么B國將永遠從這個星球消失,而B國的國土也將歸A國管轄。A國國王為了加強統(tǒng)治,會在A國和B國之間修建一條公路,即選擇原A國的某個城市和B國某個城市,修建一條連接這兩座城市的公路。?
同樣為了便于統(tǒng)治自己的國家,國家的首都會選在某個使得其他城市到它距離之和最小的城市,這里的距離是指需要經(jīng)過公路的條數(shù),如果有多個這樣的城市,編號最小的將成為首都。?
現(xiàn)在告訴你發(fā)生在X星球的戰(zhàn)事,需要你處理一些關(guān)于國家首都的信息,具體地,有如下3種信息需要處理:?
1、A x y:表示某兩個國家發(fā)生戰(zhàn)亂,戰(zhàn)勝國選擇了x城市和y城市,在它們之間修建公路(保證其中城市一個在戰(zhàn)勝國另一個在戰(zhàn)敗國)。?
2、Q x:詢問當(dāng)前編號為x的城市所在國家的首都。?
3、Xor:詢問當(dāng)前所有國家首都編號的異或和。?

輸入

第一行是整數(shù)N,M,表示城市數(shù)和需要處理的信息數(shù)。?
接下來每行是一個信息,格式如題目描述(A、Q、Xor中的某一種)。?

輸出

輸出包含若干行,為處理Q和Xor信息的結(jié)果。?

樣例輸入

10 10?
Xor?
Q 1?
A 10 1?
A 1 4?
Q 4?
Q 10?
A 7 6?
Xor?
Q 7?
Xor?

樣例輸出

11?
1?
1?
1?
2?
6?
2

題解

LCT維護子樹信息

看了好幾個小時的題解還是半懂不懂orz

先考慮連接兩棵樹

有兩個性質(zhì)

1.重心必在點數(shù)多的子樹內(nèi)

2.點數(shù)多的子樹上重心移動的距離不超過點數(shù)少的子樹的點數(shù)

然后就是連上之后,把這條路徑拉出來,dfs一遍,枚舉選哪一個點,然后判一下最優(yōu)就好了

1 // luogu-judger-enable-o2 2 //minamoto 3 #include<iostream> 4 #include<cstdio> 5 #include<algorithm> 6 using std::swap; 7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 8 char buf[1<<21],*p1=buf,*p2=buf; 9 inline int read(){ 10 #define num ch-'0' 11 char ch;bool flag=0;int res; 12 while(!isdigit(ch=getc())) 13 (ch=='-')&&(flag=true); 14 for(res=num;isdigit(ch=getc());res=res*10+num); 15 (flag)&&(res=-res); 16 #undef num 17 return res; 18 } 19 char obuf[1<<24],*o=obuf; 20 inline void print(int x){ 21 if(x>9) print(x/10); 22 *o++=x%10+48; 23 } 24 const int N=100005; 25 int fa[N],st[N],sum[N],si[N],rev[N],ch[N][2],top,s; 26 inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;} 27 inline void pushup(int x){sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+si[x]+1;} 28 inline void pushdown(int x){ 29 if(rev[x]){ 30 swap(ch[x][0],ch[x][1]); 31 rev[ch[x][0]]^=1,rev[ch[x][1]]^=1; 32 rev[x]=0; 33 } 34 } 35 void rotate(int x){ 36 int y=fa[x],z=fa[y],d=ch[y][1]==x; 37 if(!isroot(y)) ch[z][ch[z][1]==y]=x; 38 fa[x]=z,fa[y]=x,fa[ch[x][d^1]]=y,ch[y][d]=ch[x][d^1],ch[x][d^1]=y,pushup(y); 39 } 40 void down(int x){ 41 if(!isroot(x)) down(fa[x]); 42 pushdown(x); 43 } 44 void splay(int x){ 45 down(x); 46 for(int y=fa[x],z=fa[y];!isroot(x);y=fa[x],z=fa[y]){ 47 if(!isroot(y)) 48 ((ch[y][1]==x)^(ch[z][1]==y))?rotate(x):rotate(y); 49 rotate(x); 50 } 51 pushup(x); 52 } 53 void access(int x){ 54 for(int y=0;x;x=fa[y=x]) 55 splay(x),si[x]+=sum[ch[x][1]],si[x]-=sum[ch[x][1]=y],pushup(x); 56 } 57 void makeroot(int x){ 58 access(x),splay(x),rev[x]^=1; 59 } 60 int findroot(int x){ 61 access(x),splay(x),pushdown(x); 62 while(ch[x][0]) pushdown(x=ch[x][0]); 63 return x; 64 } 65 void split(int x,int y){ 66 makeroot(x),access(y),splay(y); 67 } 68 void link(int x,int y){ 69 split(x,y),fa[x]=y,si[y]+=sum[x],pushup(y); 70 } 71 void dfs(int x){ 72 pushdown(x); 73 if(ch[x][0]) dfs(ch[x][0]); 74 if(top>s) return; 75 st[++top]=x; 76 if(top>s) return; 77 if(ch[x][1]) dfs(ch[x][1]); 78 } 79 int main(){ 80 //freopen("testdata.in","r",stdin); 81 int n=read(),m=read(),res=0; 82 for(int i=1;i<=n;++i) sum[i]=1,res^=i; 83 while(m--){ 84 char c; 85 while((c=getc())!='Q'&&c!='A'&&c!='X'); 86 switch(c){ 87 case 'A':{ 88 int x=read(),y=read(); 89 int tx=findroot(x),ty=findroot(y),ts; 90 res^=tx^ty; 91 splay(tx),splay(ty); 92 if(sum[tx]>sum[ty]||(sum[tx]==sum[ty]&&x<y)) swap(x,y),swap(tx,ty); 93 s=sum[tx],ts=sum[tx]+sum[ty],link(x,y),access(x),splay(ty); 94 top=0,dfs(ty);int r=ty; 95 for(int i=1;i<=top;++i){ 96 splay(st[i]);int t=si[st[i]]+1+sum[ch[st[i]][1]]; 97 if(ts-t<t||(ts-t==t&&st[i]<=r)) r=st[i]; 98 else break; 99 /*枚舉原重心到連接點之間的路徑 100 t表示枚舉到某一點時另一棵子樹的大小 101 如果這棵子樹大于另一邊或那啥,更新答案 102 否則之前的答案最優(yōu),直接退出*/ 103 } 104 makeroot(r),res^=r; 105 break; 106 } 107 case 'Q':{ 108 int x=read(); 109 print(findroot(x)),*o++='\n'; 110 break; 111 } 112 case 'X':{ 113 print(res),*o++='\n'; 114 break; 115 } 116 } 117 } 118 fwrite(obuf,o-obuf,1,stdout); 119 return 0; 120 }

?

轉(zhuǎn)載于:https://www.cnblogs.com/bztMinamoto/p/9418679.html

總結(jié)

以上是生活随笔為你收集整理的BZOJ3510 首都的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。