zoukankan      html  css  js  c++  java
  • 数据结构整理

    今天实在是太颓了……前几天把自己认为的可做题写完了,现在刷题列表里只剩下了一些自己不(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
    ",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
    ",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
    ",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
    ",T.count(1,n));
    201             else {
    202                 scanf("%d%d",&x,&y);
    203                 if( x <= y ) printf("%d
    ",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
    ",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
    ",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
    ",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?

  • 相关阅读:
    关于checkbox的一篇博客
    如何快速学习
    for循环下的取值问题
    vue的自动更新原理
    关于word-wrap的用法;
    2016年百度面试题
    编写代码的原则
    null和defined的区别
    js的模块化加载
    springmvc注解
  • 原文地址:https://www.cnblogs.com/Cmd2001/p/8455384.html
Copyright © 2011-2022 走看看