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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

luogu P4299 首都

發布時間:2023/12/20 编程问答 65 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 首都的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。