splay<题目续集>
HDU 3436
Queue-jumpers
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4506 Accepted Submission(s): 1232
1. Top x :Take person x to the front of the queue
2. Query x: calculate the current position of person x
3. Rank x: calculate the current person at position x
Where x is in [1, N].
Ponyo is so clever that she plays the game very well while Garfield has no idea. Garfield is now turning to you for help.
In each case, the first line contains two integers N(1<=N<=10^8), Q(1<=Q<=10^5). Then there are Q lines, each line contain an operation as said above.
#include <algorithm> #include <iostream> #include <vector> #include <cstdio> #define N 200005 #define rl ch[ch[root][1]][0] using namespace std; int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } int root,cnt; int num[N],key[N],ch[N][2],pre[N],size[N]; int a[N],b[N]; int n,q; int aa[N]; int a1[N],b1[N]; void newnode(int &x,int fa,int vul){ x=vul; num[x]=size[x]=b[vul]-a[vul]+1;key[x]=a[vul]; pre[x]=fa;ch[x][0]=ch[x][1]=0; } void up(int x){ size[x]=size[ch[x][0]]+size[ch[x][1]]+num[x]; } void built(int &x,int l,int r,int fa){ if(l>r) return ; int mid=(l+r)>>1; newnode(x,fa,mid); built(ch[x][0],l,mid-1,x); built(ch[x][1],mid+1,r,x); up(x); } void rotate(int x,int kind){ int y=pre[x]; ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y];pre[y]=x;ch[x][kind]=y; up(y);up(x); } void splay(int x,int goal){ while(pre[x]!=goal){ if(pre[pre[x]]==goal){ int kind=ch[pre[x]][0]==x; rotate(x,kind); } else{ int y=pre[x]; int kind=ch[pre[y]][0]==y; if(ch[y][kind]==x){ rotate(x,!kind);rotate(x,kind); } else{ rotate(y,kind);rotate(x,kind); } } } if(goal==0) root=x; up(x); } int ef(int t){ int l=1;int r=cnt; while(l<=r){ int mid=(l+r)>>1; if(t>=a[mid]&&b[mid]>=t){ return mid; } else if(t<a[mid]) r=mid-1; else l=mid+1; } return -1; } void delet(int x){ if(ch[x][0]==0){ pre[ch[x][1]]=0; root=ch[x][1];ch[x][1]=0; up(root); } else{ int t=ch[x][0]; if(ch[t][1]==0){ pre[t]=0;root=t; pre[ch[x][1]]=t;ch[t][1]=ch[x][1]; up(root); ch[x][1]=ch[x][0]=0; } else{ while(ch[t][1]!=0){ t=ch[t][1]; } splay(t,root); pre[t]=0;root=t; pre[ch[x][1]]=t;ch[t][1]=ch[x][1]; up(root); ch[x][1]=ch[x][0]=0; } } } void Top(int x){ int y=ef(x); splay(y,0); if(ch[y][0]==0) return ; delet(y); size[y]=num[y]; int temp=root; while(ch[temp][0]!=0) temp=ch[temp][0]; splay(temp,0); pre[y]=root;ch[root][0]=y; up(root); } int Querty(int x){ int y=ef(x); splay(y,0); return size[ch[root][0]]+1; } int Rank(int x,int t){ if(t>=size[ch[x][0]]+1&&t<=size[ch[x][0]]+num[x]) return key[x]+(t-size[ch[x][0]]-1); else if(t<size[ch[x][0]]+1) return Rank(ch[x][0],t); else return Rank(ch[x][1],t-size[ch[x][0]]-num[x]); } void init(){ root=0; size[0]=pre[0]=num[0]=0; built(root,1,cnt,0); up(root); } void csh(){ n=read();q=read();char str[20]; int t1;cnt=0;int p=0; for(int i=1;i<=q;i++){ scanf(" %s",str);t1=read(); if(str[0]=='T') { a1[i]=1;b1[i]=t1; aa[p++]=t1; } else if(str[0]=='Q'){ a1[i]=2;b1[i]=t1; aa[p++]=t1; } else a1[i]=3,b1[i]=t1; } sort(aa,aa+p); int t=unique(aa,aa+p)-aa; if(t==0){ a[++cnt]=1;b[cnt]=n; return ; } if(aa[0]!=1){ a[++cnt]=1;b[cnt]=aa[0]-1; } for(int i=0;i<t-1;i++){ a[++cnt]=aa[i];b[cnt]=aa[i]; if(aa[i+1]-aa[i]>1){ a[++cnt]=aa[i]+1;b[cnt]=aa[i+1]-1; } } a[++cnt]=aa[t-1];b[cnt]=aa[t-1]; if(aa[t-1]!=n){ a[++cnt]=aa[t-1]+1;b[cnt]=n; } } int main(){ int T;T=read(); int Case=0; while(T--){ csh(); init(); //cout<<cnt<<endl; printf("Case %d:\n",++Case); for(int i=1;i<=q;i++){ if(a1[i]==1){ Top(b1[i]); } else if(a1[i]==2){ printf("%d\n",Querty(b1[i])); } else printf("%d\n",Rank(root,b1[i])); } } return 0; }
bzoj 维修序列(最经典的题
/************************************************************** Problem: 1500 User: wang9897 Language: C++ Result: Accepted Time:4916 ms Memory:26684 kb ****************************************************************/ #include <bits/stdc++.h> #define N 500005 #define INF 0x3f3f3f3f #define rl ch[ch[root][1]][0] using namespace std; int root,cnt1,cnt2; int size[N],pre[N],ch[N][2]; int flag[N],rev[N],l_max[N],r_max[N],sum_max[N],sum[N]; int key[N]; int s[N]; int a[N]; int n,q; int pos,len,c; int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } void newnode(int &x,int fa,int vul){ if(cnt2) x=s[cnt2--]; else x=++cnt1; flag[x]=rev[x]=ch[x][0]=ch[x][1]=0; pre[x]=fa;size[x]=1; sum_max[x]=a[vul]; key[x]=sum[x]=l_max[x]=r_max[x]=a[vul]; } void update_reverse(int x){ if(!x) return ; swap(ch[x][0],ch[x][1]); swap(l_max[x],r_max[x]); rev[x]^=1; } void update_same(int x,int t){ if(!x) return ; key[x]=t; sum[x]=size[x]*t;flag[x]=1; l_max[x]=r_max[x]=sum_max[x]=max(size[x]*t,t); } void down(int x){ if(flag[x]){ update_same(ch[x][0],key[x]); update_same(ch[x][1],key[x]); flag[x]=0; } if(rev[x]){ update_reverse(ch[x][0]); update_reverse(ch[x][1]); rev[x]=0; } } void up(int r){ int lson=ch[r][0],rson=ch[r][1]; size[r]=size[lson]+size[rson]+1; sum[r]=sum[lson]+sum[rson]+key[r]; l_max[r]=max(l_max[lson],sum[lson]+key[r]+max(0,l_max[rson])); r_max[r]=max(r_max[rson],sum[rson]+key[r]+max(0,r_max[lson])); sum_max[r]=max(0,r_max[lson])+key[r]+max(0,l_max[rson]); sum_max[r]=max(sum_max[r],max(sum_max[lson],sum_max[rson])); } void built(int &x,int l,int r,int fa){ if(l>r) return ; int mid=(l+r)>>1; newnode(x,fa,mid); built(ch[x][0],l,mid-1,x); built(ch[x][1],mid+1,r,x); up(x); } void rotate(int x,int kind){ int y=pre[x]; down(y);down(x); ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y];ch[x][kind]=y;pre[y]=x; up(y);up(x); } void splay(int x,int goal){ down(x); while(pre[x]!=goal){ if(pre[pre[x]]==goal){ down(pre[x]);down(x); int kind=ch[pre[x]][0]==x; rotate(x,kind); } else{ int y=pre[x]; down(pre[y]);down(y);down(x); int kind=ch[pre[y]][0]==y; if(ch[y][kind]==x){ rotate(x,!kind); rotate(x,kind); } else{ rotate(y,kind); rotate(x,kind); } } } if(goal==0) root=x; up(x); } int find1(int x,int t){ down(x); if(t==size[ch[x][0]]+1) return x; else if(t<=size[ch[x][0]]) return find1(ch[x][0],t); else return find1(ch[x][1],t-size[ch[x][0]]-1); up(x); } void inset(){ pos=read();len=read(); for(int i=1;i<=len;i++) a[i]=read(); splay(find1(root,pos+1),0); splay(find1(root,pos+2),root); built(rl,1,len,ch[root][1]); up(ch[root][1]);up(root); } void erase(int r){ if(!r) return ; s[++cnt2]=r; erase(ch[r][0]); erase(ch[r][1]); } void delet(){ pos=read();len=read(); splay(find1(root,pos),0); splay(find1(root,pos+len+1),root); erase(rl); pre[rl]=0;rl=0; up(ch[root][1]);up(root); } void Same(){ pos=read();len=read();c=read(); splay(find1(root,pos),0); splay(find1(root,pos+len+1),root); update_same(rl,c); up(ch[root][1]);up(root); } void Reverse(){ pos=read();len=read(); splay(find1(root,pos),0); splay(find1(root,pos+len+1),root); update_reverse(rl); up(ch[root][1]);up(root); } int Sum(){ pos=read();len=read(); splay(find1(root,pos),0); splay(find1(root,pos+len+1),root); return sum[rl]; } int Max_sum(){ splay(find1(root,1),0); splay(find1(root,size[root]),root); return sum_max[rl]; } void init(){ n=read();q=read(); root=cnt1=cnt2=0; ch[root][0]=ch[root][1]=pre[root]=size[root]=flag[root]=rev[root]=sum[root]=key[root]=0; l_max[root]=r_max[root]=sum_max[root]=-INF; for(int i=1;i<=n;i++) a[i]=read(); newnode(root,0,0); newnode(ch[root][1],root,0); built(rl,1,n,ch[root][1]); up(ch[root][1]);up(root); } int main(){ ios::sync_with_stdio(false); init();char str[25]; while(q--){ scanf(" %s",str); if(strcmp(str,"INSERT")==0) inset(); else if(strcmp(str,"DELETE")==0) delet(); else if(strcmp(str,"MAKE-SAME")==0) Same(); else if(strcmp(str,"REVERSE")==0) Reverse(); else if(strcmp(str,"GET-SUM")==0) printf("%d\n",Sum()); else printf("%d\n",Max_sum()); } return 0; }
bzoj 永无乡
2733: [HNOI2012]永无乡
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 4428 Solved: 2365
[Submit][Status][Discuss]
Description
永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛。如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的。现在有两种操作:B x y 表示在岛 x 与岛 y 之间修建一座新桥。Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪 座,请你输出那个岛的编号。
Input
输入文件第一行是用空格隔开的两个正整数 n 和 m,分别 表示岛的个数以及一开始存在的桥数。接下来的一行是用空格隔开的 n 个数,依次描述从岛 1 到岛 n 的重要度排名。随后的 m 行每行是用空格隔开的两个正整数 ai 和 bi,表示一开始就存 在一座连接岛 ai 和岛 bi 的桥。后面剩下的部分描述操作,该部分的第一行是一个正整数 q, 表示一共有 q 个操作,接下来的 q 行依次描述每个操作,操作的格式如上所述,以大写字母 Q 或B 开始,后面跟两个不超过 n 的正整数,字母与数字以及两个数字之间用空格隔开。 对于 20%的数据 n≤1000,q≤1000
对于 100%的数据 n≤100000,m≤n,q≤300000
Output
对于每个 Q x k 操作都要依次输出一行,其中包含一个整数,表 示所询问岛屿的编号。如果该岛屿不存在,则输出-1。
Sample Input
4 3 2 5 1
1 2
7
Q 3 2
Q 2 1
B 2 3
B 1 5
Q 2 1
Q 2 4
Q 2 3
Sample Output
2
5
1
2
/************************************************************** Problem: 2733 User: wang9897 Language: C++ Result: Accepted Time:1756 ms Memory:5200 kb ****************************************************************/ #include <bits/stdc++.h> #define N 100005 using namespace std; int ch[N][2],size[N],pre[N],key[N]; int fa[N],root[N],id[N],A[N],a[N]; int cnt,u,v,n,m,q,t1,t2; int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } void Treavel(int x) { if(x) { // cout<<x<<endl; Treavel(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d\n",x,ch[x][0],ch[x][1],pre[x],size[x],key[x]); Treavel(ch[x][1]); } } void debug(int rp) { printf("root:%d\n",rp); Treavel(rp); } int find1(int x){ if(fa[x]!=x) return fa[x]=find1(fa[x]); else return x; } int newnode(int fa,int vul){ cnt++; size[cnt]=1;key[cnt]=vul;pre[cnt]=fa; ch[cnt][0]=ch[cnt][1]=0; return cnt; } void up(int x){ size[x]=size[ch[x][1]]+size[ch[x][0]]+1; } void rotate(int x,int kind){ int y=pre[x]; ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y];ch[x][kind]=y;pre[y]=x; up(y);up(x); } void splay(int x,int goal,int &head){ while(pre[x]!=goal){ if(pre[pre[x]]==goal){ rotate(x,ch[pre[x]][0]==x); } else{ int y=pre[x]; int kind=ch[pre[y]][0]==y; if(ch[y][kind]==x){ rotate(x,!kind);rotate(x,kind); } else{ rotate(y,kind);rotate(x,kind); } } } if(goal==0) head=x; up(x); } void dfs(int x){ if(!x) return ; A[++A[0]]=x; dfs(ch[x][0]); dfs(ch[x][1]); } void insert(int &x,int t){ if(x==0){ x=t;pre[t]=x; return ; } if(key[x]>key[t]) insert(ch[x][0],t); else insert(ch[x][1],t); up(x); } void unoion(){ scanf("%d %d",&u,&v); if(fa[u]==fa[v]) return ; if(size[root[fa[u]]]>size[root[fa[v]]]) swap(u,v); A[0]=0;;dfs(root[fa[u]]); for(int i=1;i<=A[0];i++){ fa[id[A[i]]]=fa[v]; size[A[i]]=1;ch[A[i]][0]=ch[A[i]][1]=0; insert(root[fa[v]],A[i]); } } int findK(int x,int t){ if(t==size[ch[x][0]]+1) return x; else if(t<=size[ch[x][0]]) return findK(ch[x][0],t); else return findK(ch[x][1],t-size[ch[x][0]]-1); } int querty(){ scanf("%d %d",&u,&v); if(size[root[fa[u]]]<v) return -1; return id[findK(root[fa[u]],v)]; } void init(){ cnt=0;scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]);fa[i]=i;} for(int i=1;i<=m;i++){ scanf("%d%d",&u,&v); u=find1(u);v=find1(v); if(u!=v){ if(u>v) swap(u,v); fa[v]=u; } } for(int i=1;i<=n;i++){ fa[i]=find1(i);int t=newnode(1,a[i]); if(!root[fa[i]]) root[fa[i]]=t; else insert(root[fa[i]],t); id[t]=i; } // for(int i=1;i<=n;i++){ // if(root[i]){ // debug(root[i]); // } // } } int main(){ ios::sync_with_stdio(false); init(); scanf("%d",&q); char str; while(q--){ scanf(" %c",&str); if(str=='B') unoion(); else printf("%d\n",querty()); } return 0; }
poj 3481
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 17965 | Accepted: 7726 |
Description
The new founded Balkan Investment Group Bank (BIG-Bank) opened a new office in Bucharest, equipped with a modern computing environment provided by IBM Romania, and using modern information technologies. As usual, each client of the bank is identified by a positive integer K and, upon arriving to the bank for some services, he or she receives a positive integer priority P. One of the inventions of the young managers of the bank shocked the software engineer of the serving system. They proposed to break the tradition by sometimes calling the serving desk with the lowest priority instead of that with the highest priority. Thus, the system will receive the following types of request:
0 | The system needs to stop serving |
1 K P | Add client K to the waiting list with priority P |
2 | Serve the client with the highest priority and drop him or her from the waiting list |
3 | Serve the client with the lowest priority and drop him or her from the waiting list |
Your task is to help the software engineer of the bank by writing a program to implement the requested serving policy.
Input
Each line of the input contains one of the possible requests; only the last line contains the stop-request (code 0). You may assume that when there is a request to include a new client in the list (code 1), there is no other request in the list of the same client or with the same priority. An identifier K is always less than 106, and a priority P is less than 107. The client may arrive for being served multiple times, and each time may obtain a different priority.
Output
For each request with code 2 or 3, the program has to print, in a separate line of the standard output, the identifier of the served client. If the request arrives when the waiting list is empty, then the program prints zero (0) to the output.
Sample Input
2 1 20 14 1 30 3 2 1 10 99 3 2 2 0
Sample Output
0 20 30 10 0
#include <iostream> #include <algorithm> #include <cstdio> #define rl ch[ch[root][1]][0] #define lr ch[ch[root][0]][1] #define N 100005 #define INF 0x3f3f3f3f using namespace std; int ch[N][2],size[N],key[N],vul[N],pre[N]; int s[N],cnt1,cnt2,root,n; int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } int newnode(int &x,int fa,int vul1,int vul2){ if(cnt1) x=s[cnt1--]; else x=++cnt2; pre[x]=fa;size[x]=1;key[x]=vul1;vul[x]=vul2; ch[x][0]=ch[x][1]=0; return x; } void up(int x){ size[x]=size[ch[x][0]]+size[ch[x][1]]+1; } void rotate(int x,int kind){ int y=pre[x]; ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y];ch[x][kind]=y;pre[y]=x; up(y);up(x); } void splay(int x,int goal){ while(pre[x]!=goal){ if(pre[pre[x]]==goal){ rotate(x,ch[pre[x]][0]==x); } else{ int y=pre[x]; int kind=ch[pre[y]][0]==y; if(ch[y][kind]==x){ rotate(x,!kind); rotate(x,kind); } else{ rotate(y,kind); rotate(x,kind); } } } if(goal==0) root=x; up(x); } void insert(int &x,int t,int fa){ if(!x){ x=t;pre[t]=fa; return ; } if(vul[x]>vul[t]) insert(ch[x][0],t,x); else insert(ch[x][1],t,x); up(x); } int find1(int x,int t){ if(t==size[ch[x][0]]+1) return x; else if(t<=size[ch[x][0]]) return find1(ch[x][0],t); else return find1(ch[x][1],t-size[ch[x][0]]-1); } void delet(int t1){ if(size[root]<=2){ printf("0\n"); return ; } if(t1==2){ int tt=find1(root,size[root]-1); printf("%d\n",key[tt]); splay(find1(root,size[root]-2),0); splay(find1(root,size[root]),root); s[++cnt1]=rl;rl=0;up(ch[root][1]);up(root); } else{ int tt=find1(root,2); printf("%d\n",key[tt]); splay(find1(root,3),0); splay(find1(root,1),root); s[++cnt1]=lr;lr=0;up(ch[root][0]);up(root); } } void init(){ root=0;cnt1=cnt2=0; newnode(root,0,0,-1*INF); newnode(ch[root][1],root,0,INF); } int main(){ ios::sync_with_stdio(false); init(); while(scanf("%d",&n)==1){ if(n==0) break; int root1=0; if(n==1){ int t1,t2; scanf("%d %d",&t1,&t2); int t=newnode(root1,0,t1,t2); insert(root,t,0); } else{ delet(n); } } return 0; }
HDU 2475
Box
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3694 Accepted Submission(s): 1085
Jack can perform the “MOVE x y” operation to the boxes: take out box x; if y = 0, put it on the ground; Otherwise, put it inside box y. All the boxes inside box x remain the same. It is possible that an operation is illegal, that is, if box y is contained (directly or indirectly) by box x, or if y is equal to x.
In the following picture, box 2 and 4 are directly inside box 6, box 3 is directly inside box 4, box 5 is directly inside box 1, box 1 and 6 are on the ground.
The picture below shows the state after Jack performs “MOVE 4 1”:
Then he performs “MOVE 3 0”, the state becomes:
During a sequence of MOVE operations, Jack wants to know the root box of a specified box. The root box of box x is defined as the most outside box which contains box x. In the last picture, the root box of box 5 is box 1, and box 3’s root box is itself.
For each test case, the first line has an integer N (1 <= N <= 50000), representing the number of boxes.
Next line has N integers: a1, a2, a3, ... , aN (0 <= ai <= N), describing the initial state of the boxes. If ai is 0, box i is on the ground, it is not contained by any box; Otherwise, box i is directly inside box ai. It is guaranteed that the input state is always correct (No loop exists).
Next line has an integer M (1 <= M <= 100000), representing the number of MOVE operations and queries.
On the next M lines, each line contains a MOVE operation or a query:
1. MOVE x y, 1 <= x <= N, 0 <= y <= N, which is described above. If an operation is illegal, just ignore it.
2. QUERY x, 1 <= x <= N, output the root box of box x.
#include <bits/stdc++.h> #define N 100005 using namespace std; int ch[N][2],pre[N],size[N]; int num[N],p[N],fp[N],cnt,ffp[N],n,m; vector<int>vec[N]; vector<int>v_; int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } void newnode(int &x,int fa,int vul){ x=vul; pre[x]=fa;size[x]=1; ch[x][0]=ch[x][1]=0; } void up(int x){ size[x]=size[ch[x][0]]+size[ch[x][1]]+1; } void rotate(int x,int kind){ int y=pre[x]; ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y];ch[x][kind]=y;pre[y]=x; up(y);up(x); } void splay(int x,int goal){ while(pre[x]!=goal){ if(pre[pre[x]]==goal){ rotate(x,ch[pre[x]][0]==x); } else{ int y=pre[x]; int kind=ch[pre[y]][0]==y; if(ch[y][kind]==x){ rotate(x,!kind); rotate(x,kind); } else{ rotate(y,kind); rotate(x,kind); } } } up(x); } void built(int &x,int l,int r,int fa){ if(l>r) return ; int mid=(l+r)>>1; newnode(x,fa,mid); built(ch[x][0],l,mid-1,x); built(ch[x][1],mid+1,r,x); up(x); } void dfs(int v,int pre){ p[++cnt]=v;fp[v]=cnt;num[v]=1; for(int i=0;i<vec[v].size();i++){ if(vec[v][i]!=pre){ dfs(vec[v][i],v); num[v]+=num[vec[v][i]]; } } p[++cnt]=-1*v;ffp[v]=cnt; } int find1(int x,int t){ if(t==size[ch[x][0]]+1) return x; else if(t<=size[ch[x][0]]) return find1(ch[x][0],t); else return find1(ch[x][1],t-size[ch[x][0]]-1); } //操作 void move(){ int t1,t2;scanf("%d%d",&t1,&t2); if(t1==t2) return ; int temp; if(t2!=0){ splay(fp[t1],0); int tt1=p[find1(fp[t1],1)]; int p1=size[ch[fp[t1]][0]]+1; splay(fp[t2],0); int tt2=p[find1(fp[t2],1)]; int p2=size[ch[fp[t2]][0]]+1; if(tt1==tt2){ splay(ffp[t1],0); int p3=size[ch[ffp[t1]][0]]+1; if(p2>=p1&&p2<=p3) return ; } } splay(fp[t1],0); if(ch[fp[t1]][0]==0) temp=fp[t1]; else{ int root=fp[t1]; root=find1(root,size[ch[root][0]]); splay(root,0); splay(ffp[t1],root); if(size[ch[ch[root][1]][1]]==0){ temp=ch[root][1];ch[root][1]=0; up(root); } else{ int tt=size[ch[root][0]]+3+size[ch[ch[root][1]][0]]; splay(find1(root,tt),root); temp=ch[ch[root][1]][0];ch[ch[root][1]][0]=0; up(ch[root][1]);up(root); } } if(t2==0) pre[temp]=0; else{ int root=fp[t2]; splay(root,0); splay(find1(root,size[ch[root][0]]+2),root); ch[ch[root][1]][0]=temp;pre[temp]=ch[root][1]; up(ch[root][1]);up(root); } } int querty(){ int t1;scanf("%d",&t1); int root=fp[t1]; splay(root,0);int x=root; while(ch[x][0]) x=ch[x][0]; return p[x]; } void init(){ cnt=0; int t; for(int i=1;i<=n;i++){ scanf("%d",&t); if(t!=0){ vec[i].push_back(t); vec[t].push_back(i); } else{ v_.push_back(i); } } int root=0; for(int i=0;i<v_.size();i++){ dfs(v_[i],-1); built(root,cnt-num[v_[i]]*2+1,cnt,0); } } int main(){ ios::sync_with_stdio(false); int tt=0; while(scanf("%d",&n)!=EOF){ init();char str[105]; if(tt++) printf("\n"); scanf("%d",&m); while(m--){ scanf(" %s",str); if(str[0]=='Q') printf("%d\n",querty()); else move(); } for(int i=1;i<=n;i++) vec[i].clear(); v_.clear(); } return 0; }
HDU 4441
Queue Sequence
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1809 Accepted Submission(s): 506
Now you are given a queue sequence and asked to perform several operations:
1. insert p
First you should find the smallest positive number (e.g. i) that does not appear in the current queue sequence, then you are asked to insert the +i at position p (position starts from 0). For -i, insert it into the right most position that result in a valid queue sequence (i.e. when encountered with element -x, the front of the queue should be exactly x).
For example, (+1 -1 +3 +4 -3 -4) would become (+1 +2 -1 +3 +4 -2 -3 -4) after operation 'insert 1'.
2. remove i
Remove +i and -i from the sequence.
For example, (+1 +2 -1 +3 +4 -2 -3 -4) would become (+1 +2 -1 +4 -2 -4) after operation 'remove 3'.
3. query i
Output the sum of elements between +i and -i. For example, the result of query 1, query 2, query 4 in sequence (+1 +2 -1 +4 -2 -4) is 2, 3(obtained by -1 + 4), -2 correspond.
In each case, the sequence is empty initially.
The input is terminated by EOF.
After each operation, output the sum of elements between +i and -i.
#include <bits/stdc++.h> #define N 200005 #define ll long long #define INF 0x3f3f3f3f #define rl ch[ch[root][1]][0] using namespace std; int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } int size1[N],size2[N],key[N],ch[N][2],pre[N],v_[N],v__[N]; ll sum[N]; int root,cnt1,cnt2,pos; int s[N],rt1[N],rt2[N],n; typedef struct node{ int vul; }node; node d[N<<2]; void built(int root,int l,int r){ if(l==r){ d[root].vul=l; return ; } int mid=(l+r)>>1; built(root<<1,l,mid); built(root<<1|1,mid+1,r); d[root].vul=min(d[root<<1].vul,d[root<<1|1].vul); } void update(int root,int t,int l,int r,int tt){ if(l==r){ if(tt==0) d[root].vul=INF; else d[root].vul=l; return ; } int mid=(l+r)>>1; if(t<=mid) update(root<<1,t,l,mid,tt); else update(root<<1|1,t,mid+1,r,tt); d[root].vul=min(d[root<<1].vul,d[root<<1|1].vul); } void newnode(int &x,int fa,int vul){ if(cnt2) x=s[cnt2--]; else x=++cnt1; if(vul<0){ size1[x]=v_[x]=0;size2[x]=v__[x]=1; } else{ size1[x]=v_[x]=1;size2[x]=v__[x]=0; } pre[x]=fa;sum[x]=key[x]=vul; ch[x][0]=ch[x][1]=0; } int find1(int x,int t){ if(t==size1[ch[x][0]]+v_[x]) return x; else if(t<size1[ch[x][0]]+v_[x]) return find1(ch[x][0],t); else return find1(ch[x][1],t-size1[ch[x][0]]-v_[x]); } int find2(int x,int t){ if(t==size2[ch[x][0]]+v__[x]&&key[x]<0) return x; else if(t==size2[ch[x][0]]+v__[x]&&key[x]>0) return find2(ch[x][0],t); else if(t<size2[ch[x][0]]+v__[x]) return find2(ch[x][0],t); else return find2(ch[x][1],t-size2[ch[x][0]]-v__[x]); } int find3(int x,int t){ if(t==size1[ch[x][0]]+size2[ch[x][0]]+v_[x]+v__[x]) return x; else if(t<size1[ch[x][0]]+size2[ch[x][0]]+v_[x]+v__[x]) return find3(ch[x][0],t); else return find3(ch[x][1],t-size1[ch[x][0]]-size2[ch[x][0]]-v_[x]-v__[x]); } void up(int x){ sum[x]=(ll)sum[ch[x][0]]+sum[ch[x][1]]+key[x]; size1[x]=size1[ch[x][0]]+size1[ch[x][1]]+v_[x]; size2[x]=size2[ch[x][0]]+size2[ch[x][1]]+v__[x]; } void rotate(int x,int kind){ int y=pre[x]; ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y];ch[x][kind]=y;pre[y]=x; up(y);up(x); } void splay(int x,int goal){ while(pre[x]!=goal){ if(pre[pre[x]]==goal){ rotate(x,ch[pre[x]][0]==x); } else{ int y=pre[x]; int kind=ch[pre[y]][0]==y; if(ch[y][kind]==x){ rotate(x,!kind);rotate(x,kind); } else{ rotate(y,kind);rotate(x,kind); } } } if(goal==0) root=x; up(x); } //操作 void insert(){ scanf("%d",&pos);pos++; int t=d[1].vul;update(1,t,1,n,0); //cout<<t<<endl; if(size1[root]+size2[root]-1==0){ newnode(ch[root][1],root,t);rt1[t]=ch[root][1]; newnode(ch[ch[root][1]][1],ch[root][1],-1*t);rt2[t]=ch[ch[root][1]][1]; up(ch[root][1]);up(root); } else{ if(size1[root]+size2[root]==pos){ splay(find3(root,size1[root]+size2[root]),0); newnode(ch[root][1],root,t);rt1[t]=ch[root][1]; newnode(ch[ch[root][1]][1],ch[root][1],-1*t);rt2[t]=ch[ch[root][1]][1]; up(ch[root][1]);up(root); return ; } splay(find3(root,pos),0); splay(find3(root,pos+1),root); // cout<<find3(root,pos)<<" "<<find3(root,pos+1)<<endl; newnode(rl,ch[root][1],t); rt1[t]=rl; up(ch[root][1]);up(root); splay(rl,0); int tt=size1[ch[root][0]]-1; if(tt+1>size2[root]){ int size=size1[root]+size2[root]; splay(find3(root,size),root); newnode(ch[ch[root][1]][1],ch[root][1],-1*t); up(ch[root][1]);up(root); rt2[t]=ch[ch[root][1]][1]; } else{ int ttt=find2(root,tt+1); //cout<<tt<<" "<<ttt<<endl; splay(ttt,0); int size=size1[ch[root][0]]+size2[ch[root][0]]; //cout<<size<<endl; splay(find3(root,size),root); newnode(ch[ch[root][0]][1],ch[root][0],-1*t); up(ch[root][0]);up(root); rt2[t]=ch[ch[root][0]][1];} } // debug(root); } void remove(int x){ if(!ch[x][0]){ if(!ch[x][1]) return ; pre[ch[x][1]]=0;root=ch[x][1]; up(root); } else{ int y=ch[x][0]; if(!ch[y][1]){ pre[y]=0;ch[y][1]=ch[x][1]; pre[ch[x][1]]=y;root=y; up(root); } else{ while(ch[y][1]) y=ch[y][1]; splay(y,x); pre[y]=0;ch[y][1]=ch[x][1]; pre[ch[x][1]]=y;root=y; up(root); } } } void delet(){ scanf("%d",&pos);update(1,pos,1,n,1); splay(rt1[pos],0); s[++cnt2]=rt1[pos]; remove(rt1[pos]); splay(rt2[pos],0); s[++cnt2]=rt2[pos]; remove(rt2[pos]); //debug(root); } ll querty(){ scanf("%d",&pos); splay(rt1[pos],0); splay(rt2[pos],root); return sum[rl]; } void init(){ root=cnt1=cnt2=0; ch[root][0]=ch[root][1]=size1[root]=size2[root]=pre[root]=v_[root]=v__[root]=0; newnode(root,0,1); built(1,1,n); } int main(){ ios::sync_with_stdio(false); int Case=0; while(scanf("%d",&n)!=EOF){ init();char str[20]; printf("Case #%d:\n",++Case); for(int i=1;i<=n;i++){ scanf(" %s",str); if(str[0]=='i') insert(); else if(str[0]=='r') delet(); else printf("%lld\n",querty()); } } return 0; }
HDU 4453
Looploop
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2119 Accepted Submission(s): 717
The figure above shows a Looploop of 6 elments. Let's assuming the preset parameter k1 is 3, and k2 is 4.
XXX can do six operations with the toy.
1: add x
Starting from the arrow pointed element, add x to the number on the clockwise first k2 elements.
2: reverse
Starting from the arrow pointed element, reverse the first k1 clockwise elements.
3: insert x
Insert a new element with number x to the right (along clockwise) of the arrow pointed element.
4: delete
Delete the element the arrow pointed and then move the arrow to the right element.
5: move x
x can only be 1 or 2. If x = 1 , move the arrow to the left(along the counterclockwise) element, if x = 2 move the arrow to the right element.
6: query
Output the number on the arrow pointed element in one line.
XXX wants to give answers to every query in a serial of operations.
For each test case the first line contains N,M,k1,k2(2≤k1<k2≤N≤105, M≤105) indicating the initial number of elements, the total number of operations XXX will do and the two preset parameters of the toy.
Second line contains N integers ai(-104≤ai≤104) representing the N numbers on the elements in Looploop along clockwise direction. The arrow points to first element in input at the beginning.
Then m lines follow, each line contains one of the six operations described above.
It is guaranteed that the "x" in the "add","insert" and "move" operations is always integer and its absolute value ≤104. The number of elements will never be less than N during the operations.
The input ends with a line of 0 0 0 0.
#include <bits/stdc++.h> #define rl ch[ch[root][1]][0] #define N 200005 using namespace std; int ch[N][2],key[N],add[N],flag[N],size[N],pre[N]; int s[N],cnt1,a[N>>1]; int root,cnt2,key_value; int n,m,k1,k2; int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } //准备 void Treavel(int x) { if(x) { // cout<<x<<endl; Treavel(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d\n",x,ch[x][0],ch[x][1],pre[x],size[x],key[x]); Treavel(ch[x][1]); } } void debug(int rp) { printf("root:%d\n",rp); Treavel(rp); } void newnode(int &x,int fa,int vul){ if(cnt1) x=s[cnt1--]; else x=++cnt2; ch[x][1]=ch[x][0]=0; key[x]=vul;add[x]=flag[x]=0;size[x]=1; pre[x]=fa; } void update_reverse(int x){ if(!x) return ; swap(ch[x][0],ch[x][1]); flag[x]^=1; } void update_add(int x,int t){ if(!x) return ; key[x]+=t;add[x]+=t; } void push(int x){ if(flag[x]){ update_reverse(ch[x][0]); update_reverse(ch[x][1]); flag[x]=0; } if(add[x]){ update_add(ch[x][0],add[x]); update_add(ch[x][1],add[x]); add[x]=0; } } void up(int x){ size[x]=size[ch[x][0]]+size[ch[x][1]]+1; } void rotate(int x,int kind){ int y=pre[x]; push(y);push(x); ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y];ch[x][kind]=y;pre[y]=x; up(y);up(x); } void splay(int x,int goal){ push(x); while(pre[x]!=goal){ if(pre[pre[x]]==goal){ push(pre[x]);push(x); int kind=ch[pre[x]][0]==x; rotate(x,kind); } else{ int y=pre[x]; push(pre[y]);push(y);push(x); int kind=ch[pre[y]][0]==y; if(ch[y][kind]==x){ rotate(x,!kind); rotate(x,kind); } else{ rotate(y,kind); rotate(x,kind); } } } if(goal==0) root=x; up(x); } int find1(int x,int t){ push(x); if(t==size[ch[x][0]]+1) return x; else if(t<=size[ch[x][0]]) return find1(ch[x][0],t); else return find1(ch[x][1],t-size[ch[x][0]]-1); up(x); } //操作 void Add(){ int t;scanf("%d",&t); int vul=size[root]-2; if(k2>=vul) update_add(root,t); else{ if(key_value-2+k2<=vul){ splay(find1(root,key_value-1),0); splay(find1(root,key_value+k2),root); update_add(rl,t);up(ch[root][1]);up(root); } else{ int tt=key_value-2+k2-vul; splay(find1(root,key_value-1),0); splay(find1(root,size[root]),root); update_add(rl,t);up(ch[root][1]);up(root); //debug(root); splay(find1(root,1),root); if(size[ch[root][0]]-1==tt){ update_add(ch[ch[root][0]][1],t); up(ch[root][0]);up(root); } else{ splay(find1(root,tt+2),ch[root][0]); update_add(ch[ch[ch[root][0]][1]][0],t); up(ch[ch[root][0]][1]);up(ch[root][0]);up(root); } } } } void reverse(){ int vul=size[root]-2; if(k1>=vul) update_reverse(root); else{ if(key_value-2+k1<=vul){ splay(find1(root,key_value-1),0); splay(find1(root,key_value+k1),root); update_reverse(rl);up(ch[root][1]);up(root); } else{ int ttl=key_value-2+k1-vul; int ttr=vul-key_value+2; if(ttl==ttr){ splay(find1(root,key_value-1),0); splay(find1(root,size[root]),root); update_reverse(rl); splay(find1(root,1),root); splay(find1(root,ttl+2),ch[root][0]); update_reverse(ch[ch[ch[root][0]][1]][0]); swap(ch[ch[ch[root][0]][1]][0],rl); pre[rl]=ch[root][1];pre[ch[ch[ch[root][0]][1]][0]]=ch[ch[root][0]][1]; up(ch[root][1]);up(root); up(ch[ch[root][0]][1]);up(ch[root][0]);up(root); } else{ int t=min(ttl,ttr); // cout<<t<<endl; //cout<<key_value-1<<endl;; splay(find1(root,key_value-1),0); splay(find1(root,key_value+t),root); // debug(root); update_reverse(rl); //cout<<ttl<<endl; splay(find1(root,ttl-t+1),root); splay(find1(root,ttl+2),ch[root][0]); // debug(root); // cout<<ch[ch[ch[root][0]][1]][0]<<endl; update_reverse(ch[ch[ch[root][0]][1]][0]); swap(ch[ch[ch[root][0]][1]][0],rl); pre[rl]=ch[root][1];pre[ch[ch[ch[root][0]][1]][0]]=ch[ch[root][0]][1]; up(ch[root][1]);up(root); up(ch[ch[root][0]][1]);up(ch[root][0]);up(root); // debug(root); if(t==ttl){ splay(find1(root,key_value+t-1),0); splay(find1(root,size[root]),root); update_reverse(rl); up(ch[root][1]);up(root); } else{ splay(find1(root,ttl-t+2),0); splay(find1(root,1),root); update_reverse(ch[ch[root][0]][1]); up(ch[root][0]);up(root); } } } } } void inset(){ int vul;scanf("%d",&vul); splay(find1(root,key_value),0); splay(find1(root,key_value+1),root); newnode(rl,ch[root][1],vul); up(ch[root][1]);up(root); } void delet(){ int t=size[root]; splay(find1(root,key_value-1),0); splay(find1(root,key_value+1),root); s[++cnt1]=rl;rl=0;up(ch[root][1]); up(root); if(key_value==t-1) key_value=2; } void move(){ int t;scanf("%d",&t); if(t==1){ if(key_value==2) key_value=size[root]-1; else key_value=key_value-1; } else{ if(key_value==size[root]-1) key_value=2; else key_value=key_value+1; } } int querty(){ return key[find1(root,key_value)]; } void build(int &x,int l,int r,int fa){ if(l>r) return ; int mid=(l+r)>>1; newnode(x,fa,a[mid]); build(ch[x][0],l,mid-1,x); build(ch[x][1],mid+1,r,x); up(x); } void init(){ root=cnt1=cnt2=0; key_value=2; newnode(root,0,0); newnode(ch[root][1],root,0); build(rl,1,n,ch[root][1]); up(ch[root][1]);up(root); //debug(root); } int main(){ ios::sync_with_stdio(false); //freopen("test.out","w",stdout); int Case=0; while(scanf("%d%d%d%d",&n,&m,&k1,&k2)==4){ if(n==0&&m==0&&k1==0&&k2==0) break; printf("Case #%d:\n",++Case); for(int i=1;i<=n;i++) scanf("%d",&a[i]); init(); char str[20]; for(int i=1;i<=m;i++){ scanf(" %s",str); if(str[0]=='a') Add(); else if(str[0]=='r') reverse(); else if(str[0]=='i') inset(); else if(str[0]=='d') delet(); else if(str[0]=='m') move(); else printf("%d\n",querty()); } } return 0; }
HDU 3726
Graph and Queries
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4455 Accepted Submission(s): 1036
1) Deletes an edge from the graph.
The format is [D X], where X is an integer from 1 to M, indicating the ID of the edge that you should delete. It is guaranteed that no edge will be deleted more than once.
2) Queries the weight of the vertex with K-th maximum value among all vertexes currently connected with vertex X (including X itself).
The format is [Q X K], where X is an integer from 1 to N, indicating the id of the vertex, and you may assume that K will always fit into a 32-bit signed integer. In case K is illegal, the value for that query will be considered as undefined, and you should return 0 as the answer to that query.
3) Changes the weight of a vertex.
The format is [C X V], where X is an integer from 1 to N, and V is an integer within the range [-106, 106].
The operations end with one single character, E, which indicates that the current case has ended.
For simplicity, you only need to output one real number - the average answer of all queries.
There will be a blank line between two successive cases. A case with N = 0, M = 0 indicates the end of the input file and this case should not be processed by your program.
#include <bits/stdc++.h> #define N 20005 #define ll long long using namespace std; int pre[N],ch[N][2],size[N],key[N]; int fa[N],root[N],A[N]; int cnt,n,m,q; bool vis[3*N]; vector<pair<int,int> >v_; int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) { if(ch=='-')f=-1; ch=getchar(); } while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } int find2(int x) { if(x!=fa[x]) return fa[x]=find2(fa[x]); else return x; } int newnode(int fa,int vul) { cnt++; pre[cnt]=fa; size[cnt]=1; key[cnt]=vul; ch[cnt][0]=ch[cnt][1]=0; return cnt; } void up(int x) { size[x]=size[ch[x][0]]+size[ch[x][1]]+1; } void rotate(int x,int kind) { int y=pre[x]; ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y]; ch[x][kind]=y; pre[y]=x; up(y); up(x); } void splay(int x,int goal,int &head) { while(pre[x]!=goal) { if(pre[pre[x]]==goal) { rotate(x,ch[pre[x]][0]==x); } else { int y=pre[x]; int kind=ch[pre[y]][0]==y; if(ch[y][kind]==x) { rotate(x,!kind); rotate(x,kind); } else { rotate(y,kind); rotate(x,kind); } } } if(goal==0) head=x; up(x); } void insert(int &x,int t,int fa) { if(x==0) { x=t; pre[t]=fa; return ; } if(key[x]<=key[t]) insert(ch[x][1],t,x); else insert(ch[x][0],t,x); up(x); } int find1(int x,int t) { if(t==size[ch[x][0]]+1) return x; else if(t<=size[ch[x][0]]) return find1(ch[x][0],t); else return find1(ch[x][1],t-size[ch[x][0]]-1); } void delet(int x,int &head) { if(!ch[x][0]) { if(!ch[x][1]) { head=0; return ; } pre[ch[x][1]]=0; up(ch[x][1]); head=ch[x][1]; } else { int y=ch[x][0]; if(!ch[y][1]) { pre[y]=0; ch[y][1]=ch[x][1]; pre[ch[x][1]]=y; head=y; up(head); } else { while(ch[y][1]!=0) y=ch[y][1]; splay(y,x,head); pre[y]=0; pre[ch[x][1]]=y; ch[y][1]=ch[x][1]; head=y; up(head); } } } void dfs(int x) { if(!x) return ; A[++A[0]]=x; dfs(ch[x][0]); dfs(ch[x][1]); } void unoion(int t) { int u=v_[t].first; int v=v_[t].second; if(fa[u]==fa[v]) return ; if(size[root[fa[u]]]>size[root[fa[v]]]) swap(u,v); A[0]=0; dfs(root[fa[u]]); for(int i=1; i<=A[0]; i++) { fa[A[i]]=fa[v]; size[A[i]]=1; ch[A[i]][1]=ch[A[i]][0]=0; insert(root[fa[v]],A[i],0); } } void change(int u,int v) { splay(u,0,root[fa[u]]); delet(u,root[fa[u]]); size[u]=1; key[u]=v; ch[u][1]=ch[u][0]=0; insert(root[fa[u]],u,0); } int querty(int u,int t) { if(size[root[fa[u]]]<t||t<=0) return 0; // cout<<size[root[fa[u]]]<<" "<<find1(root[fa[u]],size[root[fa[u]]]-t+1)<<endl; return key[find1(root[fa[u]],size[root[fa[u]]]-t+1)]; } typedef struct node { int op; int t1,t2; } node; node d[20*N]; stack<int>s[N]; double init() { cnt=0; memset(vis,0,sizeof(vis)); memset(pre,0,sizeof(pre)); memset(size,0,sizeof(size)); memset(root,0,sizeof(root)); int t1,t2; for(int i=1; i<=n; i++) { scanf("%d",&t1); s[i].push(t1); fa[i]=i; } for(int i=1; i<=m; i++) { scanf("%d%d",&t1,&t2); v_.push_back(make_pair(t1,t2)); } char ch; int cnt1=0,cnt2=0; ll ans=0; while(1) { scanf(" %c",&ch); if(ch=='E') break; if(ch=='D') { scanf("%d",&t1); vis[t1]=1; d[++cnt1].op=1; d[cnt1].t1=t1; } else if(ch=='Q') { scanf("%d %d",&t1,&t2); cnt2++; d[++cnt1].op=2; d[cnt1].t1=t1; d[cnt1].t2=t2; } else { scanf("%d %d",&t1,&t2); s[t1].push(t2); d[++cnt1].op=3; d[cnt1].t1=t1; d[cnt1].t2=t2; } } for(int i=1; i<=m; i++) { if(vis[i]) continue; t1=find2(v_[i-1].first); t2=find2(v_[i-1].second); if(t1==t2) continue; if(t1>t2) swap(t1,t2); fa[t2]=t1; } for(int i=1; i<=n; i++) { int tt=s[i].top(); s[i].pop(); fa[i]=find2(i); int t=newnode(0,tt); if(!root[fa[i]]) root[fa[i]]=t; else insert(root[fa[i]],t,0); } for(int i=cnt1; i>=1; i--) { if(d[i].op==1) { unoion(d[i].t1-1); } else if(d[i].op==2) { ans+=querty(d[i].t1,d[i].t2); } else { int tt=s[d[i].t1].top(); s[d[i].t1].pop(); change(d[i].t1,tt); } } //cout<<ans<<endl; double ans1=ans*1.0/cnt2; return ans1; } int main() { int Case=0; while(scanf("%d %d",&n,&m)==2) { if(n==0&&m==0) break; // printf("Case %d: ",++Case); printf("Case %d: %.6f\n",++Case,init()); v_.clear(); } return 0; }
HDU 4680
About set
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 532 Accepted Submission(s): 147
but you know she is very lazy so that she wants you to help her write a program to complete this task. Surly
Zhanyl is able to solve this question, but you know, she is just lazy ...
Here is the problem, you are given n numbers, each number i has a value Ai, initially they are in different set.
Following there are m operations/querys.
The following is 5 possible kinds of oprations/querys:
1 u v: Union the set u belongs to and the set v belongs to.
2 u v: Delete u from its original set and add it to the set v belongs to.
3 u x: change the value of u to x. 1<=x<=109
4 u: query how many numbers you can choose most in set which u belongs to, so no three numbers can form a triangle.
5 u l r: query the gcd of the numbers between [l,r] in the set u belongs to, if there is no number between [l,r],you can suppose the answer is -1. 1<=l<=r<=109
Because Zhanyl is a good person, so she guarantee 1<=u,v<=n above.
You need to tell Zhanyl the answer to each query.
For each test case, the first line contains two integer n and m, n is the number of set initially, m is the number
of operations/querys.
Following line contains n integers, A1, A2, ... , An, the value of i-th number.
Following m lines, each line is a operation or query.
Note that 1<=n,m<=105, 1<=Ai<=109
#include <algorithm> #include <iostream> #include <cstdio> #include <cstring> #define N 300005 #define M 100005 #define ll long long const int INF=1<<30; using namespace std; int Gcd(int x,int y){ if(y==0) return x; else return(Gcd(y,x%y)); } int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f*x; } int rt[N],_gcd[N],ch[N][2],size[N],pre[N],key[N]; int fa[M];int A[N],id[N]; int root[M]; int cnt,n,q,u,v; void Treavel(int x) { if(x) { // cout<<x<<endl; Treavel(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d,key=%2d\n",x,ch[x][0],ch[x][1],pre[x],size[x],key[x]); Treavel(ch[x][1]); } } void debug(int rp) { printf("root:%d\n",rp); Treavel(rp); } void newnode(int &x,int fa,int vul){ cnt++;x=cnt;size[cnt]=1; pre[cnt]=fa; ch[cnt][0]=ch[cnt][1]=0; key[cnt]=_gcd[cnt]=vul; } void up(int x){ size[x]=size[ch[x][0]]+size[ch[x][1]]+1; _gcd[x]=key[x]; if(ch[x][0]) _gcd[x]=Gcd(_gcd[ch[x][0]],_gcd[x]); if(ch[x][1]) _gcd[x]=Gcd(_gcd[ch[x][1]],_gcd[x]); } void rotate(int x,int kind){ int y=pre[x]; ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y];ch[x][kind]=y;pre[y]=x; up(y);up(x); } void splay(int x,int goal,int &head){ while(pre[x]!=goal){ if(pre[pre[x]]==goal){ int kind=ch[pre[x]][0]==x; rotate(x,kind); } else{ int y=pre[x]; int kind=ch[pre[y]][0]==y; if(ch[y][kind]==x){ rotate(x,!kind); rotate(x,kind); } else{ rotate(y,kind); rotate(x,kind); } } } if(goal==0) head=x; up(x); } void inset(int &x,int t){ int head=x,p=0,val; val=key[t]; while(head){ p=head; if(val<key[head]) head=ch[head][0]; else head=ch[head][1]; } if(!p) head=t; else { pre[t]=p;ch[p][val>=key[p]]=t; splay(t,0,x); } } void dfs(int rt){ if(ch[rt][0]) dfs(ch[rt][0]); if(key[rt]!=0&&key[rt]!=INF) A[++A[0]]=rt; if(ch[rt][1]) dfs(ch[rt][1]); } void unio(){ u=read();v=read(); if(fa[u]==fa[v]) return ; if(size[root[fa[u]]]>size[root[fa[v]]]) { swap(u,v);} A[0]=0; dfs(root[fa[u]]); for(int i=1;i<=A[0];i++){ fa[id[A[i]]]=fa[v]; size[A[i]]=1;_gcd[A[i]]=key[A[i]]; ch[A[i]][0]=ch[A[i]][1]=0; inset(root[fa[v]],A[i]); //splay(A[i],root[fa[v]],root[fa[v]]); } // up(root[fa[v]]); //debug(root[fa[v]]); } int find2(int x,int k){ while(x){ // cout<<k<<" "<<size[ch[x][0]]<<endl; if(k==size[ch[x][0]]+1) return x; else if(k<=size[ch[x][0]]) x=ch[x][0]; else{ k-=(size[ch[x][0]]+1);x=ch[x][1]; } } } void update(int x,int &head){ if(!ch[x][0]){ if(!ch[x][1]) return ; pre[ch[x][1]]=0;head=ch[x][1]; up(ch[x][1]); } else{ int y=ch[x][0]; if(ch[y][1]==0){ pre[y]=0;head=y; pre[ch[x][1]]=y; ch[y][1]=ch[x][1]; up(y); } else{ while(ch[y][1]!=0) y=ch[y][1]; splay(y,x,head); pre[y]=0;head=y; pre[ch[x][1]]=y; ch[y][1]=ch[x][1]; up(y); } } } void delet(){ u=read();v=read(); if(fa[u]==fa[v]) return ; //cout<<"sb"<<endl; splay(rt[u],0,root[fa[u]]); update(rt[u],root[fa[u]]);fa[u]=fa[v]; //debug(root[fa[u]]); size[rt[u]]=1;_gcd[rt[u]]=key[rt[u]]; ch[rt[u]][0]=ch[rt[u]][1]=0; inset(root[fa[v]],rt[u]); //splay(rt[u],root[fa[v]],root[fa[v]]); // up(root[fa[v]]); // debug(rt[v]); } void change(){ u=read();v=read(); splay(rt[u],0,root[fa[u]]); update(rt[u],root[fa[u]]); //cout<<"sb"<<endl; size[rt[u]]=1;_gcd[rt[u]]=key[rt[u]]=v; ch[rt[u]][0]=ch[rt[u]][1]=0; inset(root[fa[u]],rt[u]); //splay(rt[u],root[fa[u]],root[fa[u]]); // up(root[fa[u]]); // debug(rt1); } int ans2; int ans1,ans3; void find3(int x,int t){ if(!x) return ; if(key[x]<=t){ if(key[x]>ans1) ans3=x,ans1=key[x]; find3(ch[x][1],t); } else find3(ch[x][0],t); } void find4(int x,int t){ if(!x) return ; if(key[x]>=t){ if(key[x]<ans1) ans3=x,ans1=key[x]; find4(ch[x][0],t); } else find4(ch[x][1],t); } int querty_1(){ u=read(); if(size[root[fa[u]]]<=4) return size[root[fa[u]]]-2; int t1=key[find2(root[fa[u]],2)];int t2=key[find2(root[fa[u]],3)]; int ans=2; while(1){ ans1=INF; find4(root[fa[u]],t1+t2); if(ans1==INF) return ans; ans++; t1=t2;t2=ans1; } return ans; } int querty_2(){ int l,r; u=read();l=read();r=read(); ans1=-1; find3(root[fa[u]],l-1); l=ans3; ans1=INF+1; find4(root[fa[u]],r+1); r=ans3; splay(l,0,root[fa[u]]);splay(r,root[fa[u]],root[fa[u]]); if(!ch[ch[root[fa[u]]][1]][0]) return -1; return _gcd[ch[ch[root[fa[u]]][1]][0]]; } void init(){ for(int i=1;i<=n;i++) rt[i]=read(); memset(pre,0,sizeof(pre)); memset(key,0,sizeof(key)); memset(ch,0,sizeof(ch)); memset(size,0,sizeof(size)); memset(_gcd,0,sizeof(_gcd)); memset(root,0,sizeof(root)); cnt=0; for(int i=1;i<=n;i++){ newnode(root[i],0,0); newnode(ch[root[i]][1],root[i],INF); newnode(ch[ch[root[i]][1]][0],ch[root[i]][1],rt[i]); rt[i]=ch[ch[root[i]][1]][0];id[rt[i]]=i;fa[i]=i; up(ch[root[i]][1]);up(root[i]); } } int main(){ // freopen("test.in","r",stdin); // freopen("test.out","w",stdout); int T;scanf("%d",&T);int Case=0; while(T--){ n=read();q=read(); init();int op; printf("Case #%d:\n",++Case); while(q--){ op=read(); if(op==1) unio(); else if(op==2) delet(); else if(op==3) change(); else if(op==4) printf("%d\n",querty_1()); else printf("%d\n",querty_2()); } } return 0; }