bzoj2333[SCOI2011]棘手的操作
生活随笔
收集整理的這篇文章主要介紹了
bzoj2333[SCOI2011]棘手的操作
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
可以大力寫一個平衡樹啟發式合并,除了每個連通塊維護一個平衡樹再對全局維護一個平衡樹,每個節點表示某一個連通塊的最大值.我的常數比較大,危險地卡過去了.
#include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; const int maxn=300005; struct node{node *ch[2];int Max,mark,ord,num,key,sz;node(int x,int w){ord=rand();num=x;Max=key=w;mark=0;ch[0]=ch[1]=0;sz=1;}void update(){Max=key;sz=1;if(ch[0])sz+=ch[0]->sz;if(ch[1])sz+=ch[1]->sz;if(ch[0]&&ch[0]->Max>Max)Max=ch[0]->Max;if(ch[1]&&ch[1]->Max>Max)Max=ch[1]->Max;}void add(int x){Max+=x;mark+=x;key+=x;}void pushdown(){if(mark){if(ch[0])ch[0]->add(mark);if(ch[1])ch[1]->add(mark);mark=0;}} }; node* Super; void rot(node* &rt,int t){node* c=rt->ch[t];rt->pushdown();c->pushdown();rt->ch[t]=c->ch[t^1];c->ch[t^1]=rt;rt=c;c->ch[t^1]->update();c->update(); } void Insert(node* &rt,int x,int w){//printf("%d %d\n",x,w);if(!rt){rt=new node(x,w);return;}int t=(x>rt->num);rt->pushdown();Insert(rt->ch[t],x,w);rt->update();if(rt->ch[t]->ord>rt->ord)rot(rt,t); } void remove(node* &rt,int x){if(rt->num!=x){rt->pushdown();remove(rt->ch[x>rt->num],x);rt->update();}else{if(!rt->ch[0]){rt=rt->ch[1];}else if(!rt->ch[1]){rt=rt->ch[0];}else if(rt->ch[0]->ord>rt->ch[1]->ord){rot(rt,0);remove(rt->ch[1],x);rt->update();}else{rot(rt,1);remove(rt->ch[0],x);rt->update();}} } int ufs[maxn]; int find(int x){return (x==ufs[x])?x:ufs[x]=find(ufs[x]); } node* root[maxn]; void Union(node* rt1,node* &rt2){if(!rt1)return;Insert(rt2,rt1->num,rt1->key);rt1->pushdown();Union(rt1->ch[0],rt2);Union(rt1->ch[1],rt2);delete rt1; } void link(int a,int b){int ra=find(a),rb=find(b);if(root[ra]->sz>root[rb]->sz)swap(ra,rb);ufs[ra]=rb;Union(root[ra],root[rb]);remove(Super,ra);remove(Super,rb);Insert(Super,find(a),root[find(a)]->Max); } void incr(node* rt,int x,int w){rt->pushdown();if(x==rt->num){rt->key+=w;rt->update();return;}else{incr(rt->ch[x>rt->num],x,w);rt->update();return;} } int getkey(node* rt,int x){rt->pushdown();if(rt->num==x)return rt->key;return getkey(rt->ch[x>rt->num],x); } int Globalmark=0; int main(){int n;scanf("%d",&n);int x;for(int i=1;i<=n;++i){scanf("%d",&x);Insert(Super,i,x);root[i]=new node(i,x);ufs[i]=i;}char buf[5];int m;scanf("%d",&m);int a,b;for(int i=1;i<=m;++i){scanf("%s",buf);if(buf[0]=='U'){scanf("%d%d",&a,&b);if(find(a)!=find(b))link(a,b);}else if(buf[0]=='A'){if(buf[1]=='1'){scanf("%d%d",&a,&b);incr(root[find(a)],a,b);remove(Super,find(a));Insert(Super,find(a),root[find(a)]->Max);}else if(buf[1]=='2'){scanf("%d%d",&a,&b);root[find(a)]->add(b);incr(Super,find(a),b);}else{scanf("%d",&b);Globalmark+=b;}}else if(buf[0]=='F'){if(buf[1]=='1'){scanf("%d",&a);printf("%d\n",getkey(root[find(a)],a)+Globalmark);}else if(buf[1]=='2'){scanf("%d",&a);printf("%d\n",root[find(a)]->Max+Globalmark);}else{printf("%d\n",Super->Max+Globalmark);}}}return 0; }?
轉載于:https://www.cnblogs.com/liu-runda/p/6396883.html
總結
以上是生活随笔為你收集整理的bzoj2333[SCOI2011]棘手的操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MOV指令在32位汇编程序和64位汇编程
- 下一篇: Qt之可重入与线程安全