BZOJ 2843 LCT

这还是道LCT的题,跟着czl做了好多LCT的题啊!没事,czl带我飞!加油,不错,挺顺利的。加油!1592毫秒, 第一次考虑了代码量, 我写这个花了 2800的代码长度, 然而czl只有1900, 代码简化还是很重要啊!

  1 #include<cstdio>
  2 #include<iostream>
  3 #define lc c[k][0]
  4 #define rc c[k][1]
  5 #define rep(i,j,k) for(int i = j; i <= k; i++)
  6 #define maxn 30233
  7 using namespace std;
  8
  9 int c[maxn][2], pa[maxn], w[maxn], sum[maxn];
 10 bool rev[maxn];
 11 int read()
 12 {
 13     int s = 0,t = 1; char c = getchar();
 14     while( !isdigit(c) ){
 15         if( c == ‘-‘ ) t = -1; c = getchar();
 16     }
 17     while( isdigit(c) ){
 18         s=  s * 10+ c - ‘0‘; c = getchar();
 19     }
 20     return s * t;
 21 }
 22
 23 bool root(int x)
 24 {
 25     int k = pa[x];
 26     return lc != x && rc != x;
 27 }
 28
 29 void maintain(int k)
 30 {
 31     sum[k] = sum[lc] + sum[rc] + w[k];
 32 }
 33
 34 void rorate(int k)
 35 {
 36     int fa = pa[k], gfa = pa[fa];
 37     int l = c[fa][1] == k, r = l ^ 1;
 38     if( !root(fa) ){
 39         c[gfa][c[gfa][1] == fa] = k;
 40     }
 41     pa[fa] = k, pa[k] = gfa, pa[c[k][r]] = fa;
 42     c[fa][l] = c[k][r], c[k][r] = fa; maintain(fa), maintain(k);
 43 }
 44
 45 void pushdown(int k)
 46 {
 47     if( rev[k] ){
 48         rev[k] ^= 1, rev[lc] ^= 1, rev[rc] ^= 1;
 49         swap(lc,rc);
 50     }
 51 }
 52
 53 int q[maxn];
 54 void splay(int k)
 55 {
 56     int top = 0; q[++top] = k;
 57     for(int x = k; !root(x); x = pa[x] )
 58        q[++top] = pa[x];
 59     while( top ) pushdown(q[top--]);
 60     while( !root(k) ){
 61         int fa = pa[k], gfa = pa[fa];
 62         if( !root(fa) ){
 63             if( c[gfa][1] == fa ^ c[fa][1] == k ) rorate(k);
 64             else rorate(fa);
 65         }
 66         rorate(k);
 67     }
 68 }
 69
 70 void access(int k)
 71 {
 72     for(int t = 0; k; t = k, k = pa[k])
 73        splay(k), rc = t, maintain(k);
 74 }
 75
 76 void makeroot(int k)
 77 {
 78     access(k), splay(k), rev[k] ^= 1;
 79 }
 80
 81 void link(int x,int y)
 82 {
 83     makeroot(x), pa[x] = y;
 84 }
 85
 86 void split(int x,int y)
 87 {
 88     makeroot(x), access(y), splay(y); c[y][0] = pa[x] = 0;
 89     maintain(y);
 90 }
 91
 92 int find(int k)
 93 {
 94     access(k), splay(k);
 95     while( lc ) k = lc;
 96     return k;
 97 }
 98
 99 int query(int x,int y)
100 {
101     makeroot(x), access(y), splay(y); return sum[y];
102 }
103
104 int main()
105 {
106     int n = read();
107     rep(i,1,n) w[i] = read(); char  c[20];
108     int m = read();
109     rep(i,1,m){
110         scanf("%s", c);
111         if( c[0] == ‘b‘ ) {
112             int x = read(), y = read();
113             int kx = find(x), ky = find(y);
114             if( kx != ky ) {
115                 puts("yes");
116                 link(x,y);
117             }
118             else puts("no");
119         }
120         if( c[0] == ‘e‘ ){
121             int x = read(), y = read();
122             int kx = find(x), ky = find(y);
123             if( kx != ky ) puts("impossible");
124             else printf("%d\n", query(x,y));
125         }
126         if( c[0] == ‘p‘ ){
127             int x = read(), y = read();
128             splay(x); w[x] = y; maintain(x);
129         }
130     }
131     return 0;
132 }
时间: 2024-10-07 19:56:16

BZOJ 2843 LCT的相关文章

bzoj 2631 LCT

/************************************************************** Problem: 2631 User: wangyucheng Language: C++ Result: Accepted Time:18408 ms Memory:9252 kb ****************************************************************/ #include<iostream> #include

BZOJ 2843: 极地旅行社( LCT )

LCT.. ------------------------------------------------------------------------ #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #define rep( i , n ) for( int i = 0 ; i < n ; ++i ) #define clr( x , c ) me

BZOJ 2843: 极地旅行社 lct splay

http://www.lydsy.com/JudgeOnline/problem.php?id=2843 https://blog.csdn.net/clove_unique/article/details/50992341 和之前那道题lct求两点距离用lca不同,这道题因为给的边的两个端点是没有顺序的(没法直接按照给的点直接将某个点连到树上),所以bridge需要区间翻转的操作,因为splay维护的是链,所以区间翻转相当于将叶子变成了根,根变成叶子(链翻转过来),然后再把此时的根(x)连到y

bzoj 3669 lct维护最小生成树

大概题意:给一个无向图,有a,b两种边权,找一条从1到n的路径,使得max(a[i])+max(b[i])最小a[i],b[i]表示该路径上的边的对应权. 如果用类似最短路的DP来做,显然每个点的状态就必须是一个集合,保存的是一个下凸的点集,表示到达这个点的最小的a,b,这样肯定会挂,但该该种做法已经无法再优化或减少状态了. 考虑枚举其中一个权值b0,然后只考虑所有b权值小于等于b0的边,然后变成简单的问题,因为这个b0不满足二分三分之类的性质,所以肯定不能每次重建图,跑DP,最终的做法是从小到

BZOJ 4668 LCT

思路: 这不是LCT裸题嘛23333 (好像并查集+按秩合并就可以搞了 我还是too young) 维护边权的话 就新加一个点 代表边 这个点想线段的两个端点连边就好了 //By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=1000050; int n,m,op,xx,yy,top,lastans,T; int fa[N],ch[N][2],q[N],maxx[N],rev[N],v[N],f[N];

BZOJ 2002 LCT板子题

思路: LCT啊... (分块也行) 不过YOUSIKI出了一道"弹飞大爷" 就不能用分块水过去了 //By SiriusRen #include <cstdio> #include <algorithm> using namespace std; const int N=200050; int fa[N],ch[N][2],rev[N],size[N],n,op,q[N],top,a[N],m,xx,yy; bool isroot(int x){return

【BZOJ 2843】极地旅行社

复习一下LinkCutTree的模板. #include<cstdio> #include<cstring> #include<algorithm> #define N 30003 #define read(x) x=getint() using namespace std; struct node *null; struct node { node *ch[2], *fa; int d, sum; short rev; bool pl() {return fa->

BZOJ 3514 LCT+主席树

思路: //By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=400500; int n,m,k,type,ch[N][2],fa[N],minn[N],rev[N],q[N],top,pre[N]; int root[N],tree[N*50],lson[N*50],rson[N*50],cnt,xx,yy,ans; struct Road{int x,y,wei;}road[N]; bool isr

BZOJ 2049 LCT

Orz 黄学长, 当然也要感谢自己(这次打的比较顺利,虽然题目操作很少,也比较简单),加油, 相信自己, 会更强大的, 但还是要虚心, 才会有更大的进步. 不过还是有点不懂,找个时间,问一下czl吧! 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define rep(i,j,k) for(int i = j; i <= k; i++) 5 #define lc c[k][0] 6 #