luogu P4299 首都
生活随笔
收集整理的這篇文章主要介紹了
luogu P4299 首都
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述
在X星球上有N個國家,每個國家占據著X星球的一座城市。由于國家之間是敵對關系,所以不同國家的兩個城市是不會有公路相連的。
X星球上戰亂頻發,如果A國打敗了B國,那么B國將永遠從這個星球消失,而B國的國土也將歸A國管轄。A國國王為了加強統治,會在A國和B國之間修建一條公路,即選擇原A國的某個城市和B國某個城市,修建一條連接這兩座城市的公路。
同樣為了便于統治自己的國家,國家的首都會選在某個使得其他城市到它距離之和最小的城市,這里的距離是指需要經過公路的條數,如果有多個這樣的城市,編號最小的將成為首都。
現在告訴你發生在X星球的戰事,需要你處理一些關于國家首都的信息,具體地,有如下3種信息需要處理:
- A x y:表示某兩個國家發生戰亂,戰勝國選擇了x城市和y城市,在它們之間修建公路(保證其中城市一個在戰勝國另一個在戰敗國)。
- Q x:詢問當前編號為x的城市所在國家的首都。
- Xor:詢問當前所有國家首都編號的異或和。
題解
有link操作還詢問重心,是讓我們在維護LCT的時候維護一下重心。
這道題用到了LCT的很多性質。
比如說我們link了兩棵樹,那么我們拿出兩棵樹的重心,那么重心一定在這兩條鏈的路徑上,我們把這條鏈split出來。
根據splay的性質,這條鏈構成的splay的高度是期望log的。
然后我們就可以從根開始搜索了。
既然是log的,那么我們就可以用類似樹上二分的方法找了。
連通性這種東西用并查集維護就可以了。
LCT維護子樹信息時link一定要splay(y)!!!!!
代碼
#include<iostream> #include<cstdio> #include<cstring> #define N 100009 using namespace std; char sh[10]; int f[N],ch[N][2],s[N],si[N],fa[N],n,m,st[N],xoR; bool rev[N]; inline int rd(){int x=0;char c=getchar();bool f=0;while(!isdigit(c)){if(c=='-')f=1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}return f?-x:x; } inline int find(int x){return f[x]=f[x]==x?x:find(f[x]);} inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;} inline bool ge(int x){return ch[fa[x]][1]==x;} inline void pushup(int x){s[x]=s[ch[x][0]]+s[ch[x][1]]+si[x]+1;} inline void pushdown(int x){if(rev[x]){rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;rev[x]^=1;swap(ch[x][0],ch[x][1]); } } inline void rotate(int x){int y=fa[x],o=ge(x);if(isroot(x))return; ch[y][o]=ch[x][o^1];fa[ch[y][o]]=y;if(!isroot(y))ch[fa[y]][ge(y)]=x;fa[x]=fa[y];fa[y]=x;ch[x][o^1]=y;pushup(y);pushup(x); } inline void push(int x){if(!isroot(x))push(fa[x]);pushdown(x); } inline void splay(int x){push(x);while(!isroot(x)){ int y=fa[x];if(isroot(y))rotate(x);else rotate(ge(x)==ge(y)?y:x),rotate(x); }pushup(x); } inline void access(int x){for(int y=0;x;y=x,x=fa[x]){splay(x);si[x]-=s[y];si[x]+=s[ch[x][1]];ch[x][1]=y;pushup(x); } } inline void makeroot(int x){access(x);splay(x);rev[x]^=1;} inline void split(int x,int y){makeroot(x);access(y);splay(y);} inline void link(int x,int y){split(x,y);fa[x]=y;si[y]+=s[x];pushup(y);} inline int search(int x){int suml=0,sumr=0,rs,ls,sum=s[x]>>1,o=s[x]&1,now=2e9,xx,yy; while(x){pushdown(x);xx=suml+s[ls=ch[x][0]];yy=sumr+s[rs=ch[x][1]];if(xx<=sum&&yy<=sum){if(o){now=x;break;}else if(x<now)now=x;}if(xx<yy)suml+=s[ls]+si[x]+1,x=rs;else sumr+=s[rs]+si[x]+1,x=ls;}return now; } int main(){ n=rd();m=rd();int x,y;for(int i=1;i<=n;++i)s[i]=1,f[i]=i,xoR^=i; for(int i=1;i<=m;++i){scanf("%s",sh);if(sh[0]=='A'){x=rd();y=rd();//if(find(x)==find(y))continue;link(x,y);x=find(x);y=find(y);split(x,y);int z=search(y);xoR=xoR^x^y^z;f[x]=f[y]=f[z]=z;}else if(sh[0]=='Q'){x=rd();printf("%d\n",find(x));}else printf("%d\n",xoR); }return 0; }轉載于:https://www.cnblogs.com/ZH-comld/p/10193648.html
總結
以上是生活随笔為你收集整理的luogu P4299 首都的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python + selenium +
- 下一篇: PTA乙级1044