数据结构整理

今天实在是太颓了……前几天把自己认为的可做题写完了,现在刷题列表里只剩下了一些自己不(xia)愿(ji)意(ba)写(zhao)的毒瘤题了,实在不愿意做……

于是整个上午睡觉,然后发现自己连水题都不愿意写了……
还是来整理一下这些天写过的题目吧……

 

Bzoj3123:

传送门: http://www.lydsy.com/JudgeOnline/problem.php?id=3123

首先这题如果不强制在线,我们把这棵树建出来然后主席树乱搞一下就好了(皮这一下很开心吗?)

然后考虑在线怎么做,我们可以按秩合并,也就多一个log罢了,于是我们得到了一个优秀的nlog^2n做法:每次把较小的联通块的主席树扔掉,然后重建即可。

其余的细节?就是顺便用倍增维护一下LCA,用并查集维护一下联通块size就好了。

关于GC(垃圾回收):我写的有0号点作为空树的主席树是没法GC的,只能二分数组大小然后卡过。这个我也问过梁大爷,如果不用0号树,直接用0号点做所有空节点的话,是可以GC的。话说这题时限本来就卡,写了GC不就是TLE(雾)。

代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define debug cout
  6 using namespace std;
  7 const int maxn=8e4+1e2,maxl=20;
  8  
  9 struct ChairmanTree {
 10     int l[maxn*200],r[maxn*200],lson[maxn*200],rson[maxn*200],sum[maxn*200],cnt;
 11     inline int NewNode() {
 12         return ++cnt;
 13     }
 14     inline void build(int pos,int ll,int rr) {
 15         l[pos] = ll , r[pos] = rr;
 16         if( ll == rr ) return;
 17         const int mid = ( ll + rr ) >> 1;
 18         build(lson[pos]=NewNode(),ll,mid);
 19         build(rson[pos]=NewNode(),mid+1,rr);
 20     }
 21     inline void insert(int pos,int pre,int x) {
 22         l[pos] = l[pre] , r[pos] = r[pre] ,
 23         lson[pos] = lson[pre] , rson[pos] = rson[pre];
 24         if( l[pos] == r[pos] ) {
 25             sum[pos] = sum[pre] + 1;
 26             return;
 27         } const int mid = ( l[pos] + r[pos] ) >> 1;
 28         if( x <= mid ) insert(lson[pos]=NewNode(),lson[pre],x);
 29         else insert(rson[pos]=NewNode(),rson[pre],x);
 30         sum[pos] = sum[lson[pos]] + sum[rson[pos]];
 31     }
 32     inline int cl(int a1,int a2,int b1,int b2) {
 33         return sum[lson[a1]] + sum[lson[a2]] - sum[lson[b1]] - sum[lson[b2]];
 34     }
 35     inline int query(int a1,int a2,int b1,int b2,int k) {
 36         if( l[a1] == r[a1] ) return l[a1];
 37         int sl = cl(a1,a2,b1,b2);
 38         if( k <= sl ) return query(lson[a1],lson[a2],lson[b1],lson[b2],k);
 39         return query(rson[a1],rson[a2],rson[b1],rson[b2],k-sl);
 40     }
 41 }tr;
 42 struct UnionFindSet {
 43     int fa[maxn],siz[maxn];
 44     inline int findfa(int x) {
 45         if( fa[x] == x ) return x;
 46         siz[fa[x]] += siz[x] , siz[x] = 0;
 47         return fa[x] = findfa(fa[x]);
 48     }
 49     inline int getsiz(int x) {
 50         return siz[findfa(x)];
 51     }
 52     inline void merge(int x,int y) {
 53         x = findfa(x) , y = findfa(y);
 54         siz[x] += siz[y] , siz[y] = 0;
 55         fa[y] = x;
 56     }
 57     inline void init(int n) {
 58         for(int i=1;i<=n;i++) fa[i] = i , siz[i] = 1;
 59     }
 60 }ufs;
 61  
 62 int in[maxn],srt[maxn],slen;
 63 int s[maxn],t[maxn<<2],nxt[maxn<<2],cnt;
 64 int fa[maxn][maxl],root[maxn],dep[maxn];
 65 int n;
 66  
 67 inline void addedge(int from,int to) {
 68     t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt;
 69 }
 70 inline void recycle(int pos) {
 71     for(int at=s[pos];at;at=nxt[at])
 72         if( t[at] != fa[pos][0] )
 73             recycle(t[at]);
 74     memset(fa[pos],0,sizeof(fa[pos]));
 75 }
 76 inline void build(int pos) {
 77     root[pos] = tr.NewNode();
 78     tr.insert(root[pos],root[fa[pos][0]],in[pos]);
 79     for(int i=1;i<maxl;i++) fa[pos][i] = fa[fa[pos][i-1]][i-1];
 80     for(int at=s[pos];at;at=nxt[at])
 81         if( t[at] != fa[pos][0] ) {
 82             fa[t[at]][0] = pos , dep[t[at]] = dep[pos] + 1;
 83             build(t[at]);
 84         }
 85 }
 86 inline int lca(int x,int y) {
 87     if( dep[x] < dep[y] ) swap(x,y);
 88     for(int i=maxl-1;~i;i--)
 89         if( dep[x] - dep[y] >= ( 1 << i ) )
 90             x = fa[x][i];
 91     if( x == y ) return x;
 92     for(int i=maxl-1;~i;i--)
 93         if( fa[x][i] != fa[y][i] )
 94             x = fa[x][i] , y = fa[y][i];
 95     return fa[x][0];
 96 }
 97 inline int getroot(int x) {
 98     for(int i=maxl-1;~i;i--)
 99         if( fa[x][i] )
100             x = fa[x][i];
101     return x;
102 }
103 inline int kth(int x,int y,int k) {
104     int l = lca(x,y) , f = fa[l][0];
105     return tr.query(root[x],root[y],root[l],root[f],k);
106 }
107 inline void merge(int x,int y) {
108     int sx = ufs.getsiz(x) , sy = ufs.getsiz(y);
109     if( sx < sy ) swap(x,y);
110     recycle(getroot(y));
111     ufs.merge(x,y);
112     addedge(x,y) , addedge(y,x);
113     fa[y][0] = x , dep[y] = dep[x] + 1;
114     build(y);
115 }
116  
117 inline void init() {
118     memcpy(srt+1,in+1,sizeof(int)*n);
119     sort(srt+1,srt+1+n) , slen = unique(srt+1,srt+1+n) - srt - 1;
120     for(int i=1;i<=n;i++) in[i] = lower_bound(srt+1,srt+1+slen,in[i]) - srt;
121     root[0] = tr.NewNode();
122     tr.build(root[0],1,slen);
123     ufs.init(n);
124     for(int i=1;i<=n;i++)
125         if( !root[i] ) build(i);
126     for(int i=1;i<=n;i++)
127         if( fa[i][0] ) ufs.merge(fa[i][0],i);
128 }
129  
130 int main() {
131     static int m,os,la;
132     static char o[10];
133     scanf("%*d%d%d%d",&n,&m,&os) , la = 0;
134     for(int i=1;i<=n;i++) scanf("%d",in+i);
135     for(int i=1,a,b;i<=m;i++) {
136         scanf("%d%d",&a,&b);
137         addedge(a,b) , addedge(b,a);
138     }
139     init();
140     for(int i=1,x,y,k;i<=os;i++) {
141         scanf("%s%d%d",o,&x,&y) , x ^= la , y ^= la;
142         if( *o == 'Q' ) {
143             scanf("%d",&k) , k ^= la;
144             la = kth(x,y,k);
145             la = srt[la];
146             printf("%d\n",la);
147         } else {
148             merge(x,y);
149         }
150     }
151     return 0;
152 }
View Code

 

Bzoj1453:

传送门: http://www.lydsy.com/JudgeOnline/problem.php?id=1453

各位大佬看来这不是LCT水题吗?或者cdq+并查集乱搞一下。

然而为什么我一开始想到的是n^2m的暴力?

考虑暴力怎么优化?如果我们把一维建成线段树,另一位继续暴力,是不是就能卡过去了呢?

我们在线段树的每个节点上维护区间左边一列位置,右边一列位置,左边一列的id,右边一列的id,每个id是否出现在左、右,区间内的黑色、白色联通块数,然后合并一下就可以了。

关于这玩意怎么合并?我们考虑用并查集维护每个格子属于哪个集合。我们先把右区间的id全部加400的偏移量,然后让左区间的右和右区间的左去合并。合并完成后统计合并失败后被封锁(无法接触左右边界)的黑白联通块数并更新答案,然后重新离散化id并维护每个id在左右是否出现了。

这题复杂度不怎么卡,常数写的很丑也给过了QAQ。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 const int maxn=2e2+1e1,maxl=8e2+1e1;
  6  
  7 int in[maxn][maxn],tp[maxl];
  8 int n;
  9  
 10 struct UnionFindSet {
 11     int fa[maxl];
 12     inline int findfa(int x) {
 13         return fa[x] == x ? x : fa[x] = findfa(fa[x]);
 14     }
 15     inline void merge(int x,int y) {
 16         x = findfa(x) , y = findfa(y);
 17         if( x != y ) fa[x] = y;
 18     }
 19     inline void resfa(int k) {
 20         for(int i=1;i<=k;i++) fa[i] = i;
 21     }
 22 }ufs;
 23  
 24 struct Node {
 25     int fal[maxn],far[maxn],sta[maxn<<1],l,r,inb,inw; // sta means a number's appear place .
 26     Node() {
 27         memset(fal,0,sizeof(fal));
 28         memset(far,0,sizeof(far));
 29         memset(sta,0,sizeof(sta));
 30         l = r = inb = inw = 0;
 31     }
 32     inline void rebuild() {
 33         static int cov[maxl] , cnt;
 34         memset(cov,0,sizeof(cov)) , cnt = 0;
 35         for(int i=1;i<=n;i++) if( !cov[fal[i]] ) cov[fal[i]] = ++cnt;
 36         for(int i=1;i<=n;i++) if( !cov[far[i]] ) cov[far[i]] = ++cnt;
 37         for(int i=1;i<=n;i++) fal[i] = cov[fal[i]] , sta[fal[i]] |= 1; // 1 means appeared on left .
 38         for(int i=1;i<=n;i++) far[i] = cov[far[i]] , sta[far[i]] |= 2; // 2 means appeared on right .
 39     }
 40     inline void getfa() {
 41         for(int i=1;i<=n;i++) fal[i] = ufs.findfa(fal[i]) , far[i] = ufs.findfa(far[i]);
 42     }
 43     friend Node operator + (const Node &a,const Node &fakeb) { // we have to operate b.
 44         Node ret,b=fakeb;
 45         ret.l = a.l , ret.r = b.r , ret.inb = a.inb + b.inb , ret.inw = a.inw + b.inw;
 46         int mil = a.r , mir = b.l;
 47         ufs.resfa(n<<2) , memset(tp,0,sizeof(tp));
 48         for(int i=1;i<=n;i++)
 49             b.fal[i] += n<<1 , b.far[i] += n<<1;
 50         memcpy(ret.fal,a.fal,sizeof(a.fal)) , memcpy(ret.far,b.far,sizeof(b.far));
 51         for(int i=1;i<=n;i++)
 52             if( in[i][mil] == in[i][mir] ) ufs.merge(a.far[i],b.fal[i]);
 53         for(int i=1;i<=n;i++)
 54             tp[ufs.findfa(ret.fal[i])] |= 1 , tp[ufs.findfa(ret.far[i])] |= 2;
 55         for(int i=1;i<=n;i++) {
 56             if( !tp[ufs.findfa(a.far[i])] ) {
 57                 tp[ufs.findfa(a.far[i])] = 4;
 58                 if( in[i][mil] == 0 ) ++ret.inw;
 59                 else ++ret.inb;
 60             }
 61             if( !tp[ufs.findfa(b.fal[i])] ) {
 62                 tp[ufs.findfa(b.fal[i])] = 4;
 63                 if( in[i][mir] == 0 ) ++ret.inw;
 64                 else ++ret.inb;
 65             }
 66         }
 67         ret.getfa() , ret.rebuild();
 68         return ret;       
 69     }
 70     inline void set(int p) {
 71         l = r = p , inb = inw = 0;
 72         int c = 0;
 73         for(int i=1;i<=n;i++) {
 74             if( i == 1 || in[i][p] != in[i-1][p] ) fal[i] = far[i] = ++c , sta[c] = 3;
 75             else fal[i] = far[i] = fal[i-1];
 76         }
 77     }
 78     inline void count(int& retb,int& retw) {
 79         static bool vis[maxn<<1];
 80         memset(vis,0,sizeof(vis));
 81         retb = inb , retw = inw;
 82         for(int i=1;i<=n;i++)
 83             if( !vis[fal[i]] ) {
 84                 vis[fal[i]] = 1;
 85                 if( in[i][l] == 0 ) ++retw;
 86                 else ++retb;
 87             }
 88         for(int i=1;i<=n;i++)
 89             if( !vis[far[i]] ) {
 90                 vis[far[i]] = 1;
 91                 if( in[i][r] == 0 ) ++retw;
 92                 else ++retb;
 93             }
 94     }
 95 }ns[maxn<<3];
 96  
 97 int l[maxn<<3],r[maxn<<3],lson[maxn<<3],rson[maxn<<3],cnt;
 98  
 99 inline void build(int pos,int ll,int rr) {
100     l[pos] = ll , r[pos] = rr;
101     if( ll == rr ) {
102         ns[pos].set(ll);
103         return;
104     } const int mid = ( ll + rr ) >> 1;
105     build(lson[pos]=++cnt,ll,mid) , build(rson[pos]=++cnt,mid+1,rr);
106     ns[pos] = ns[lson[pos]] + ns[rson[pos]];
107 }
108 inline void update(int pos,int tar) {
109     if( tar < l[pos] || r[pos] < tar ) return;
110     if( l[pos] == r[pos] ) {
111         ns[pos].set(l[pos]);
112         return;
113     }
114     update(lson[pos],tar) , update(rson[pos],tar);
115     ns[pos] = ns[lson[pos]] + ns[rson[pos]];
116 }
117  
118 inline void printans() {
119     static int ab,aw;
120     ns[1].count(ab,aw);
121     printf("%d %d\n",ab,aw);
122 }
123 int main() {
124     static int m;
125     scanf("%d",&n);
126     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",in[i]+j);
127     build(cnt=1,1,n);
128     scanf("%d",&m);
129     for(int i=1,x,y;i<=m;i++) {
130         scanf("%d%d",&x,&y);
131         in[x][y] = !in[x][y];
132         update(1,y);
133         printans();
134     }
135     return 0;
136 }
View Code

 

 

Bzoj3796:

传送门: http://www.lydsy.com/JudgeOnline/problem.php?id=3786

这真不是LCT水题?等等,子树加,LCT做不了。

考虑用DFS序解决子树加的问题,关于子树加,就是区间加。关于更换父亲?就是区间移动喽。

对于区间移动,就是先提取区间,然后把他放到新的父亲的右边的第一个位置即可。

如果你懒得加哨兵节点,代码细节较多注意讨论。

代码:

  1  
  2 #pragma GCC optimize(3)
  3 #include<cstdio>
  4 #include<cctype>
  5 #define lli long long int
  6 const int maxn=2e5+1e2;
  7  
  8 int st,ed;
  9  
 10 struct Splay {
 11     int ch[maxn][2],fa[maxn],tpe[maxn],siz[maxn],cnt,root;
 12     lli sum[maxn],dat[maxn],lazy[maxn];
 13      
 14     inline void set(int pos,lli add) {
 15         if( !pos ) return;
 16         dat[pos] += tpe[pos] * add , sum[pos] += siz[pos] * add , lazy[pos] += add;
 17     }
 18     inline void push(int pos) {
 19         if( !lazy[pos] ) return;
 20         set(ch[pos][0],lazy[pos]) ,
 21         set(ch[pos][1],lazy[pos]) ,
 22         lazy[pos] = 0;
 23     }
 24     inline void up(int fa,int son) {
 25         if( !son ) return;
 26         siz[fa] += siz[son] , sum[fa] += sum[son];
 27     }
 28     inline void upgrade(int pos) {
 29         siz[pos] = tpe[pos] , sum[pos] = dat[pos];
 30         up(pos,ch[pos][0]) ,
 31         up(pos,ch[pos][1]) ;
 32     }
 33     inline int gid(int x) {
 34         return x == ch[fa[x]][1];
 35     }
 36     inline void rotate(int x) {
 37         const int f = fa[x] , id = gid(x);
 38         push(f) , push(x);
 39         fa[x] = fa[f];
 40         if( fa[f] ) ch[fa[f]][gid(f)] = x;
 41         else root = x;
 42         ch[f][id] = ch[x][id^1];
 43         if( ch[x][id^1] ) fa[ch[x][id^1]] = f;
 44         ch[x][id^1] = f , fa[f] = x;
 45         upgrade(f) , upgrade(x);
 46     }
 47     inline void splay(int pos) {
 48         while( pos != root ) {
 49             if( fa[fa[pos]] ) rotate(fa[pos]);
 50             rotate(pos);
 51         }
 52     }
 53     inline void upchain(int pos) {
 54         while( pos != root ) {
 55             upgrade(pos) , pos = fa[pos];
 56         }
 57     }
 58     inline int insert(int tp,int va) {
 59         if( !root ) {
 60             root = ++cnt , tpe[root] = tp , sum[root] = dat[root] = tp * va;
 61             return root;
 62         }
 63         int ret = ++cnt , now = root;
 64         tpe[ret] = tp , sum[ret] = dat[ret] = tp * va;
 65         while( ch[now][1] ) now = ch[now][1];
 66         ch[now][1] = ret , fa[ret] = now;
 67         upchain(ret);
 68         splay(ret);
 69         return ret;
 70     }
 71     inline void mkrson(int pos) {
 72         while( pos != ch[root][1] ) {
 73             if( fa[pos] != ch[root][1] ) rotate(fa[pos]);
 74             rotate(pos);
 75         }
 76     }
 77     inline void pushchain(int pos) {
 78         if( pos != root ) pushchain(fa[pos]);
 79         push(pos);
 80     }
 81     inline int getprv(int pos) {
 82         if( pos == st ) return -1;
 83         if( ch[pos][0] ) {
 84             int ret = ch[pos][0];
 85             while( ch[ret][1] ) ret = ch[ret][1];
 86             return ret;
 87         }
 88         while( pos == ch[fa[pos]][0] ) pos = fa[pos];
 89         return fa[pos];
 90     }
 91     inline int getnxt(int pos) {
 92         if( pos == ed ) return -1;
 93         if( ch[pos][1] ) {
 94             int ret = ch[pos][1];
 95             while( ch[ret][0] ) ret = ch[ret][0];
 96             return ret;
 97         }
 98         while( pos == ch[fa[pos]][1] ) pos = fa[pos];
 99         return fa[pos];
100     }
101     inline void update(int posl,int posr,lli add) {
102         int prv = getprv(posl) , nxt = getnxt(posr);
103         if( !~prv && !~nxt ) {
104             set(root,add);
105             return;
106         }
107         splay(prv) , mkrson(nxt);
108         int pos = ch[ch[root][1]][0];
109         set(pos,add);
110         splay(pos);
111     }
112     inline int segment(int posl,int posr) { // assert posl != in[1] && posr != out[1] .
113         int prv = getprv(posl) , nxt = getnxt(posr);
114         splay(prv) , mkrson(nxt);
115         return ch[ch[root][1]][0];
116     }
117     inline void move(int posl,int posr,int nfa) {
118         int pos = segment(posl,posr);
119         pushchain(fa[pos]);
120         ch[fa[pos]][gid(pos)] = 0 , fa[pos] = 0;
121         splay(nfa);
122         int tar = ch[nfa][1];
123         while( ch[tar][0] ) tar = ch[tar][0];
124         pushchain(tar);
125         ch[tar][0] = pos , fa[pos] = tar;
126         splay(pos);
127     }
128     inline lli query(int pos) {
129         int nxt = getnxt(pos);
130         splay(nxt);
131         return sum[ch[root][0]];
132     }
133 }T;
134  
135 int s[maxn>>1],t[maxn],nxt[maxn];
136 int in[maxn>>1],out[maxn>>1];
137 int w[maxn>>1];
138  
139 inline void addedge(int from,int to) {
140     static int cnt = 0;
141     t[++cnt] = to , nxt[cnt] = s[from] , s[from] = cnt;
142 }
143 inline void dfs(int pos) {
144     in[pos] = T.insert(1,w[pos]);
145     for(int at=s[pos];at;at=nxt[at])
146         dfs(t[at]);
147     out[pos] = T.insert(-1,w[pos]);
148 }
149  
150 inline char nextchar() {
151     const static int BS = 1 << 21;
152     static char buf[BS],*st=buf+BS,*ed=buf+BS;
153     if( st == ed ) ed = buf + fread(st=buf,1,BS,stdin);
154     return st == ed ? -1 : *st++;
155 }
156 inline int getint() {
157     int ret = 0 , ch;
158     while( !isdigit(ch=nextchar()) );
159     do ret=ret*10+ch-'0'; while( isdigit(ch=nextchar()) );
160     return ret;
161 }
162 inline char realchar() {
163     char ret;
164     while( !isalpha(ret=nextchar()) ) ;
165     return ret;
166 }
167 int main() {
168     static int n,m;
169     static char o;
170     n = getint();
171     for(int i=2,f;i<=n;i++) {
172         f = getint();
173         addedge(f,i);
174     }
175     for(int i=1;i<=n;i++) w[i] = getint();
176     dfs(1) , st = in[1] , ed = out[1];
177     m = getint();
178     for(int i=1,p,x;i<=m;i++) {
179         o = realchar() , p = getint();
180         if( o == 'Q' ) printf("%lld\n",T.query(in[p]));
181         else {
182             x = getint();
183             if( o == 'F' ) T.update(in[p],out[p],x);
184             else T.move(in[p],out[p],in[x]);
185         }
186     }
187     return 0;
188 }
View Code

 

 

Bzoj1493:

传送门: http://www.lydsy.com/JudgeOnline/problem.php?id=1493

前两个操作可以写用变量维护,然后线段树可做,细节较多。

好的,细节太多?我选择splay。

Rotate就是把区间最后一段移动到最前,Filp就是把区间[2,n]翻转。

然后swap看做两个单点的区间染色,我们只需要实现区间染色,统计区间颜色数量就可以了。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 const int maxn=5e5+1e2;
  6  
  7 int n;
  8  
  9 struct Splay {
 10     int ch[maxn][2],fa[maxn],col[maxn][2],dat[maxn],sum[maxn],siz[maxn],root,cnt; // sum includes color on sides .
 11     int rev[maxn],recol[maxn]; // rev >= recol , so you must push recol first before pusing rev .
 12      
 13     Splay() {
 14         memset(recol,-1,sizeof(recol));
 15     }
 16     inline void fill(int pos,int cc) {
 17         if( !pos ) return;
 18         col[pos][0] = col[pos][1] = dat[pos] = recol[pos] = cc , sum[pos] = 1;
 19     }
 20     inline void initfill(int pos,int cc) {
 21         col[pos][0] = col[pos][1] = dat[pos] = cc , sum[pos] = 1;
 22     }
 23     inline void applyrev(int pos) {
 24         if( !pos ) return;
 25         swap( ch[pos][0] , ch[pos][1] ) , swap( col[pos][0] , col[pos][1] );
 26     }
 27     inline void push(int pos) {
 28         if( ~recol[pos] ) {
 29             fill(ch[pos][0],recol[pos]) , fill(ch[pos][1],recol[pos]);
 30             recol[pos] = -1;
 31         }
 32         if( rev[pos] ) {
 33             rev[ch[pos][0]] ^= 1 , rev[ch[pos][1]] ^= 1;
 34             applyrev(ch[pos][0]) , applyrev(ch[pos][1]);
 35             rev[pos] = 0;
 36         }
 37     }
 38     inline void upgrade(int pos) {
 39         col[pos][0] = col[pos][1] = dat[pos] , sum[pos] = 1 ,
 40         siz[pos] = 1;
 41         if( ch[pos][0] ) {
 42             sum[pos] = sum[pos] + sum[ch[pos][0]] - ( col[ch[pos][0]][1] == col[pos][0] ) , 
 43             col[pos][0] = col[ch[pos][0]][0] ,
 44             siz[pos] += siz[ch[pos][0]] ;
 45         }
 46         if( ch[pos][1] ) {
 47             sum[pos] = sum[pos] + sum[ch[pos][1]] - ( col[pos][1] == col[ch[pos][1]][0] ) ,
 48             col[pos][1] = col[ch[pos][1]][1]  ,
 49             siz[pos] += siz[ch[pos][1]] ;
 50         }
 51     }
 52     inline int gid(int x) {
 53         return x == ch[fa[x]][1];
 54     }
 55     inline void rotate(int x) {
 56         push(fa[x]) , push(x);
 57         const int f = fa[x] , id = gid(x);
 58         fa[x] = fa[f];
 59         if( fa[f] ) ch[fa[f]][gid(f)] = x;
 60         else root = x;
 61         ch[f][id] = ch[x][id^1];
 62         if( ch[x][id^1] ) fa[ch[x][id^1]] = f;
 63         ch[x][id^1] = f , fa[f] = x;
 64         upgrade(f) , upgrade(x);
 65     }
 66     inline void splay(int pos) {
 67         while( root != pos ) {
 68             if( fa[fa[pos]] ) rotate(fa[pos]);
 69             rotate(pos);
 70         }
 71     }
 72     inline void upchain(int x) {
 73         while( x ) {
 74             upgrade(x) , 
 75             x = fa[x];
 76         }
 77     }
 78     inline void pushchain(int x) {
 79         if( fa[x] ) pushchain(fa[x]);
 80         push(x);
 81     }
 82     inline void insert(int cc) {
 83         if( !root ) {
 84             root = ++cnt , siz[cnt] = 1;
 85             initfill(root,cc);
 86             return;
 87         }
 88         int now = root;
 89         while( push(now) , ch[now][1] ) now = ch[now][1];
 90         ch[now][1] = ++cnt , siz[cnt] = 1 , fa[cnt] = now;
 91         initfill(cnt,cc) , upchain(cnt);
 92         splay(cnt);
 93     }
 94     inline int kth(int k) {
 95         int now = root;
 96         while( 1 ) {
 97             push(now);
 98             if( k < 0 ) exit(0);
 99             if( k == siz[ch[now][0]] + 1 ) return now;
100             if( k <= siz[ch[now][0]] ) now = ch[now][0];
101             else k -= siz[ch[now][0]] + 1 , now = ch[now][1];
102         }
103         throw "It Shouldn't Be Here ." ; 
104     }
105     inline void insertleft(int pos) {
106         int now = root;
107         while( push(now) , ch[now][0] ) now = ch[now][0];
108         ch[now][0] = pos , fa[pos] = now;
109         upchain(now);
110     }
111     inline void move(int k) {
112         int mip = kth(n-k);
113         splay(mip) , pushchain(mip);
114         int pos = ch[mip][1]; ch[mip][1] = fa[pos] = 0;
115         upchain(mip);
116         insertleft(pos);
117         splay(pos);
118     }
119     inline void filp() {
120         int tar = kth(1);
121         splay(tar);
122         rev[ch[tar][1]] ^= 1 , applyrev(ch[tar][1]);
123         splay(ch[tar][1]);
124     }
125     inline int getp(int k) {
126         int pos = kth(k);
127         return dat[pos];
128     }
129     inline void mkrson(int pos) {
130         while( pos != ch[root][1] ) {
131             if( fa[pos] != ch[root][1] ) rotate(fa[pos]);
132             rotate(pos);
133         }
134     }
135     inline void print(int st,int ed,int cc) {
136         if( st == 1 && ed == n ) {
137             fill(root,cc);
138         } else if( st == 1 ) {
139             int nxt = kth(ed+1);
140             splay(nxt);
141             fill(ch[root][0],cc);
142             splay(ch[root][0]);
143         } else if( ed == n ) {
144             int prv = kth(st-1);
145             splay(prv);
146             fill(ch[root][1],cc);
147             splay(ch[root][1]);
148         } else {
149             int nxt = kth(ed+1) , prv = kth(st-1);
150             splay(prv) , mkrson(nxt);
151             fill(ch[ch[root][1]][0],cc);
152             splay(ch[ch[root][1]][0]);
153         }
154     }
155     inline int count(int st,int ed) {
156         if( st == 1 && ed == n ) {
157             return max ( sum[root] - ( col[root][0] == col[root][1] ) , 1 );
158         } else if( st == 1 ) {
159             int nxt = kth(ed+1);
160             splay(nxt);
161             return sum[ch[root][0]];
162         } else if( ed == n ) {
163             int prv = kth(st-1);
164             splay(prv);
165             return sum[ch[root][1]];
166         } else {
167             int nxt = kth(ed+1) , prv = kth(st-1);
168             splay(prv) , mkrson(nxt);
169             return sum[ch[ch[root][1]][0]];
170         }
171     }
172     inline int count(int st,int ed,int& rc) {
173         if( st == 1 ) {
174             int nxt = kth(ed+1);
175             splay(nxt) , rc = col[ch[root][0]][0];
176             return sum[ch[root][0]];
177         } else if( ed == n ) {
178             int prv = kth(st-1);
179             splay(prv) , rc = col[ch[root][1]][1];
180             return sum[ch[root][1]];
181         }
182         throw "It Shouldn't Be Here ." ; 
183     }
184 }T;
185  
186 int main() {
187     static int m;
188     static char o[10];
189     scanf("%d%*d",&n);
190     for(int i=1,x;i<=n;i++) {
191         scanf("%d",&x);
192         T.insert(x);
193     }
194      
195     scanf("%d",&m);
196     for(int i=1,x,y,k;i<=m;i++) {
197         scanf("%s",o);
198         if( *o == 'F' ) T.filp();
199         else if( *o == 'C' ) {
200             if( o[1] != 'S' ) printf("%d\n",T.count(1,n));
201             else {
202                 scanf("%d%d",&x,&y);
203                 if( x <= y ) printf("%d\n",T.count(x,y));
204                 else {
205                     int cx,cy,ans;
206                     ans = T.count(x,n,cx) + T.count(1,y,cy);
207                     ans -= ( cx == cy );
208                     printf("%d\n",ans);
209                 }
210             }
211         } else {
212             if( *o == 'R' ) {
213                 scanf("%d",&k);
214                 T.move(k);
215             } else {
216                 scanf("%d%d",&x,&y);
217                 if( *o == 'S' ) {
218                     int cx = T.getp(x) , cy = T.getp(y);
219                     T.print(x,x,cy) , T.print(y,y,cx);
220                 } else {
221                     scanf("%d",&k);
222                     if( x <= y ) T.print(x,y,k);
223                     else T.print(x,n,k) , T.print(1,y,k);
224                 }
225             }
226         }
227     }
228     return 0;
229 }
View Code

 

 

Bzoj2594:

传送门: http://www.lydsy.com/JudgeOnline/problem.php?id=2594

把自始至终一直存在的边先求最小生成树放进去,我们倒序考虑,就是不断加边维护最小生成树了。

LCT没法维护边权,拆边为点,维护点权就好了。

写太丑会T,叫你写快读你非得scanf。

代码:

  1 #pragma GCC optimize(2)
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cctype>
  5 const int maxn=1e5+1e2,maxm=1e6+1e2,maxp=1.2e6+1e2;
  6  
  7 int n,m,q;
  8 struct LCT {
  9     int ch[maxp][2],fa[maxp],v[maxp],mx[maxp],rev[maxp];
 10      
 11     inline void applyrev(int pos) {
 12         if( !pos ) return;
 13         rev[pos] ^= 1 ,
 14         std::swap(ch[pos][0],ch[pos][1]);
 15     }
 16     inline void update(int pos) {
 17         mx[pos] = pos;
 18         if( v[mx[ch[pos][0]]] > v[mx[pos]] ) mx[pos] = mx[ch[pos][0]];
 19         if( v[mx[ch[pos][1]]] > v[mx[pos]] ) mx[pos] = mx[ch[pos][1]];
 20     }
 21     inline void push(int pos) {
 22         if( !rev[pos] ) return;
 23         applyrev(ch[pos][0]) ,
 24         applyrev(ch[pos][1]) ,
 25         rev[pos] = 0;
 26     }
 27     inline int gid(int x) {
 28         return x == ch[fa[x]][1];
 29     }
 30     inline bool isroot(int x) {
 31         return x != ch[fa[x]][0] && x != ch[fa[x]][1];
 32     }
 33     inline void rotate(int x) {
 34         push(fa[x]) , push(x);
 35         const int f = fa[x] , id = gid(x);
 36         fa[x] = fa[f];
 37         if( !isroot(f) ) ch[fa[f]][gid(f)] = x;
 38         ch[f][id] = ch[x][id^1];
 39         if( ch[x][id^1] ) fa[ch[x][id^1]] = f;
 40         ch[x][id^1] = f , fa[f] = x;
 41         update(f) , update(x);
 42     }
 43     inline void pushchain(int x) {
 44         if( fa[x] ) pushchain(fa[x]);
 45         push(x);
 46     }
 47     inline void splay(int x) {
 48         pushchain(x);
 49         while( !isroot(x) ) {
 50             if( !isroot(fa[x]) ) rotate(fa[x]);
 51             rotate(x);
 52         }
 53     }
 54     inline void access(int x) {
 55         int y = 0;
 56         while( x ) {
 57             splay(x) , ch[x][1] = y , update(x) ,
 58             y = x , x = fa[x];
 59         }
 60     }
 61     inline void mkroot(int x) {
 62         access(x) , splay(x) , applyrev(x);
 63     }
 64     inline void link(int x,int y) {
 65         mkroot(x) , fa[x] = y;
 66     }
 67     inline void cut(int x,int y) {
 68         mkroot(x);
 69         access(y) , splay(y);
 70         fa[x] = ch[y][0] = 0 , update(y); // now we assert x == ch[y][0] ( it must be true ) .
 71     }
 72     inline int query(int x,int y) {
 73         mkroot(x);
 74         access(y) , splay(y);
 75         return mx[y]; // y shouldn't have ch[1] .
 76     }
 77 }t;
 78  
 79 struct UnionFindSet {
 80     int fa[maxn];
 81     inline int findfa(int x) {
 82         return fa[x] == x ? x : fa[x] = findfa(fa[x]);
 83     }
 84     inline void merge(int x,int y) {
 85         x = findfa(x) , y = findfa(y);
 86         if( x != y ) fa[y] = x;
 87     }
 88     inline void init() {
 89         for(int i=1;i<=n;i++) fa[i] = i;
 90     }
 91 }ufs;
 92  
 93 struct Edge {
 94     int x,y,w,id,sta;
 95     friend bool operator < (const Edge &a,const Edge &b) {
 96         return a.x != b.x ? a.x < b.x : a.y < b.y;
 97     }
 98 }es[maxm];
 99 bool cmp(const Edge &a,const Edge &b) {
100     return a.w < b.w;
101 }
102  
103 int ope[maxn],x[maxn],y[maxn],id[maxn],ans[maxn]; // ope == 1 means modify .
104  
105 inline void getans() {
106     for(int i=q;i;i--) {
107         if( !ope[i] ) {
108             int p = t.query(x[i],y[i]);
109             ans[i] = t.v[p];
110         } else {
111             if( ufs.findfa(x[i]) != ufs.findfa(y[i]) ) {
112                 ufs.merge(x[i],y[i]);
113                 t.link(x[i],id[i]+n) , t.link(y[i],id[i]+n);
114             } else {
115                 int p = t.query(x[i],y[i]);
116                 if( t.v[p] > t.v[id[i]+n] ) {
117                     t.cut(x[i],p) , t.cut(y[i],p);
118                     t.link(x[i],id[i]+n) , t.link(y[i],id[i]+n);
119                 }
120             }
121         }
122     }
123 }
124 inline void pre() {
125     std::sort(es+1,es+1+m,cmp) , ufs.init();
126     for(int i=1;i<=m;i++)
127         if( !es[i].sta && ufs.findfa(es[i].x) != ufs.findfa(es[i].y) ) {
128             ufs.merge(es[i].x,es[i].y);
129             t.link(es[i].x,es[i].id+n) , t.link(es[i].y,es[i].id+n);
130         }
131 }
132  
133 inline void init() {
134     for(int i=1;i<=m;i++) {
135         const int id = i + n;
136         t.v[id] = es[i].w , t.mx[id] = id;
137     }
138     std::sort(es+1,es+1+m);
139     for(int i=1;i<=q;i++) 
140         if( ope[i] ) {
141             int at = std::lower_bound(es+1,es+1+m,(Edge){x[i],y[i],0,0,0}) - es;
142             es[at].sta = 1 , id[i] = es[at].id;
143         }
144 }
145  
146 inline char nextchar() {
147     const int BS = 1 << 22;
148     static char buf[BS],*st=buf+BS,*ed=buf+BS;
149     if( st == ed ) ed = buf + fread(st=buf,1,BS,stdin);
150     return st == ed ? -1 : *st++;
151 }
152 inline int getint() {
153     int ret = 0 , ch;
154     while( !isdigit(ch=nextchar()) );
155     do ret=ret*10+ch-'0'; while( isdigit(ch=nextchar()) );
156     return ret;
157 }
158  
159 int main() {
160     n = getint() , m = getint() , q = getint();
161     for(int i=1;i<=m;i++) {
162         es[i].x = getint() , es[i].y = getint() , es[i].w = getint() , es[i].id = i;
163         if( es[i].x > es[i].y ) std::swap( es[i].x , es[i].y );
164     }
165     for(int i=1;i<=q;i++) {
166         ope[i] = getint() , x[i] = getint() , y[i] = getint() , --ope[i];
167         if( x[i] > y[i] ) std::swap( x[i] , y[i] );
168     }
169     init() , pre() , getans();
170     for(int i=1;i<=q;i++) if( !ope[i] ) printf("%d\n",ans[i]);
171     return 0;
172 }
View Code

 

 

Bzoj5020:

传送门: http://www.lydsy.com/JudgeOnline/problem.php?id=5020

准确地说着不算是数据结构题,而是一道数学题。

他给的那三个函数显然都不可加,所以我们需要把他泰勒展开近似成多项式函数,然后LCT乱搞。

关于泰勒展开公式?

我们维护到x^17就行了,这种纠结的题多了T少了WA真是没办法……

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 const int maxn=1e5+1e2,maxl=20,lim=17;
  6  
  7 double fac[maxl],c[maxl][maxl];
  8  
  9 struct LCT {
 10     struct Node {
 11         double dat[maxl];
 12          
 13         inline void in(const double &a,const double &b,const int &tpe) {
 14             static double pa[maxl],pb[maxl];
 15             if( tpe != 3 ) {
 16                 *pa = *pb = 1;
 17                 for(int i=1;i<=lim;i++) pa[i] = pa[i-1] * a , pb[i] = pb[i-1] * b;
 18             }
 19             memset(dat,0,sizeof(dat));
 20             if( tpe == 1 ) {
 21                 for(int i=1,t=1;i<=lim;i+=2,t=-t)
 22                     for(int j=0;j<=i;j++)
 23                         dat[j] += pa[j] * pb[i-j] * c[i][j] * t / fac[i];
 24             } else if( tpe == 2 ) {
 25                 for(int i=0;i<=lim;i++)
 26                     for(int j=0;j<=i;j++)
 27                         dat[j] += pa[j] * pb[i-j] * c[i][j] / fac[i];
 28             } else if( tpe == 3 ) {
 29                 dat[1] = a , dat[0] = b;
 30             }
 31         }
 32         inline double calc(const double &x) {
 33             static double pows[maxl];
 34             *pows = 1;
 35             for(int i=1;i<=lim;i++) pows[i] = pows[i-1] * x;
 36             double ret = 0;
 37             for(int i=0;i<=lim;i++) ret += dat[i] * pows[i];
 38             return ret;
 39         }
 40          
 41         friend Node operator + (const Node &a,const Node &b) {
 42             Node ret; memset(ret.dat,0,sizeof(ret.dat));
 43             for(int i=0;i<=lim;i++) ret.dat[i] = a.dat[i] + b.dat[i];
 44             return ret;
 45         }
 46     }dat[maxn],sum[maxn];
 47     int ch[maxn][2],fa[maxn],rev[maxn];
 48     inline void apply(int pos) {
 49         if( !pos ) return;
 50         rev[pos] ^= 1 ,
 51         swap(ch[pos][0],ch[pos][1]);
 52     }
 53     inline void push(int pos) {
 54         if( !rev[pos] ) return;
 55         apply(ch[pos][0]) , apply(ch[pos][1]) ,
 56         rev[pos] = 0;
 57     }
 58     inline void update(int x) {
 59         sum[x] = dat[x];
 60         if( ch[x][0] ) sum[x] = sum[x] + sum[ch[x][0]];
 61         if( ch[x][1] ) sum[x] = sum[x] + sum[ch[x][1]]; 
 62     }
 63     inline bool isrt(int x) {
 64         return x != ch[fa[x]][0] && x != ch[fa[x]][1];
 65     }
 66     inline bool gid(int x) {
 67         return x == ch[fa[x]][1];
 68     }
 69     inline void rotate(int x) {
 70         push(fa[x]) , push(x);
 71         const int f = fa[x] , id = gid(x);
 72         fa[x] = fa[f];
 73         if( !isrt(f) ) ch[fa[f]][gid(f)] = x;
 74         ch[f][id] = ch[x][id^1];
 75         if( ch[x][id^1] ) fa[ch[x][id^1]] = f;
 76         ch[x][id^1] = f , fa[f] = x;
 77         update(f) , update(x);
 78     }
 79     inline void pushchain(int x) {
 80         if( !isrt(x) ) pushchain(fa[x]);
 81         push(x);
 82     }
 83     inline void upchain(int x) {
 84         while(1) {
 85             update(x);
 86             if( isrt(x) ) break;
 87             x = fa[x];
 88         }
 89     }
 90     inline void splay(int x) {
 91         pushchain(x);
 92         while( !isrt(x) ) {
 93             if( !isrt(fa[x]) ) rotate(fa[x]);
 94             rotate(x);
 95         }
 96     }
 97     inline void access(int x) {
 98         int y = 0;
 99         while( x ) {
100             splay(x) , ch[x][1] = y , update(x);
101             y = x , x = fa[x];
102         }
103     }
104     inline void mkrt(int x) {
105         access(x) , splay(x) , apply(x);
106     }
107     inline void link(int x,int y) {
108         mkrt(x) , fa[x] = y;
109     }
110     inline void cut(int x,int y) {
111         mkrt(x) , access(y) , splay(y);
112         ch[y][0] = fa[x] = 0 , update(y);
113     }
114     inline int findfa(int x) {
115         while( fa[x] ) x = fa[x];
116         return x;
117     }
118     inline Node query(int x,int y) {
119         mkrt(x) , access(y) , splay(y);
120         return sum[y];
121     }
122 }T;
123 inline void pre() {
124     *fac = 1;
125     for(int i=1;i<=lim;i++) fac[i] = fac[i-1] * i;
126     c[0][0] = 1;
127     for(int i=1;i<=lim;i++) {
128         c[i][0] = 1;
129         for(int j=1;j<=i;j++) c[i][j] = c[i-1][j-1] + c[i-1][j];
130     }
131 }
132  
133 int main() {
134     static int n,m;
135     static char o[10];
136     static double a,b;
137     pre();
138     scanf("%d%d%*s",&n,&m);
139     for(int i=1,t;i<=n;i++) {
140         scanf("%d%lf%lf",&t,&a,&b);
141         T.dat[i].in(a,b,t);
142     }
143     for(int i=1,t,x,y;i<=m;i++) {
144         scanf("%s",o);
145         if( *o == 'a' ) {
146             scanf("%d%d",&x,&y) , ++x , ++y;
147             T.link(x,y);
148         } else if( *o == 't' ) {
149             scanf("%d%d%lf",&x,&y,&a) , ++x , ++y;
150             if( T.findfa(x) != T.findfa(y) ) puts("unreachable");
151             else {
152                 LCT::Node ans = T.query(x,y);
153                 printf("%.8e\n",ans.calc(a));
154             }
155         } else if( *o == 'm' ) {
156             scanf("%d%d%lf%lf",&x,&t,&a,&b) , ++x;
157             T.splay(x);
158             T.dat[x].in(a,b,t);
159         } else if( *o == 'd' ) {
160             scanf("%d%d",&x,&y) , ++x , ++y;
161             T.cut(x,y);
162         }
163     }
164     return 0;
165 }
View Code

 

 

最后说几句废话(好像这篇全都是废话?):

为什么我这种辣鸡颓佬还能当Bzoj年榜Rank1?

posted @ 2018-02-20 16:55  Cmd2001  阅读(254)  评论(0编辑  收藏  举报