zoukankan      html  css  js  c++  java
  • [BZOJ 3514]Codechef MARCH14 GERALD07加强版

    这题的做法很巧妙,我却写的很作死……

    今天算是狠狠的又补了一边 link-cut-tree ,完了又是发现自己很 SX 

    考虑已经有 i 条边构成的图,现在要加入第 i+1 跳边

    那么有两种情况:1.要么成环 2.要么不成环 (废话)

    我们认为成环的边是没有贡献的,不成环的边是有贡献的

    答案就是统计 l..r 条边中有贡献的边一共有几条,然后用 n 减一下

    我们再次定义第 i 条边加入后构成的环中最早被加入的边是 ntr[i] ,然后从第一条边起,每次在加入第 i 条边后,把第 ntr[i] 条边删除(233…)

    此时图始终呈一个生成森林

    那么 l..r 条边中有贡献的边的条数就是 l..r 条边中 ntr[i]<l 的边数

    因为 ntr[i]>=l 的说明这条边在加入后与 l..i 中的某条边构成了环,显然这是一条毫无贡献的边

    ntr 数组可以用 link-cut-tree 来解决,每次在 u 和 v 间连一条权为 w 的边等价于把 u 和 v 连向一个权值为 w 的点,我们就解决了化边权为点权的问题

    至于后面那个主席树就可以了……

    这真是一道可怕的数据结构题

      1 #include <cstdio>
      2 const int inf=0x7FFFFFFF;
      3 const int sizeOfPoint=200002;
      4 
      5 int n, m, k, type;
      6 int u[sizeOfPoint], v[sizeOfPoint];
      7 int time[sizeOfPoint<<1], ntr[sizeOfPoint];
      8 inline int getint();
      9 inline void putint(int);
     10 template<class type> inline void swap(type & a, type & b) {type t=a; a=b; b=t;}
     11 
     12 struct node
     13 {
     14     int id;
     15     node * min;
     16     bool rev;
     17     node * f, * c[2];
     18     inline node():id(0), rev(0) {min=this; f=c[0]=c[1]=this;}
     19     inline void maintain() {min=this; if (time[c[0]->min->id]<time[min->id]) min=c[0]->min; if (time[c[1]->min->id]<time[min->id]) min=c[1]->min;}
     20     inline void pushdown() {if (rev) swap(c[0], c[1]), c[0]->rev^=1, c[1]->rev^=1, rev=0;}
     21 };
     22 node * null=new node();
     23 node memoryOfLct[sizeOfPoint<<1], * portOfLct=memoryOfLct;
     24 node * t[sizeOfPoint<<1];
     25 inline node * newnode(int _id) {node * ret=portOfLct++; ret->id=_id; ret->min=ret; ret->rev=0; ret->f=ret->c[0]=ret->c[1]=null; return ret;}
     26 inline void rotate(node * x, int d) {node * y=x->f, * z=y->f; (y->c[d]=x->c[d^1])->f=y; (x->c[d^1]=y)->f=x; y->maintain(); if (z->c[0]==y) z->c[0]=x; if (z->c[1]==y) z->c[1]=x; x->f=z;}
     27 inline void splay(node * x)
     28 {
     29     node * y, * z; bool d, dd;
     30     x->pushdown();
     31     while ((y=x->f)!=null && (y->c[0]==x || y->c[1]==x))
     32         if ((z=y->f)!=null && (z->c[0]==y || z->c[1]==y))
     33         {
     34             z->pushdown(), y->pushdown(), x->pushdown();
     35             d=y->c[1]==x, dd=z->c[1]==y;
     36             if (d==dd) rotate(y, dd), rotate(x, d);
     37             else rotate(x, d), rotate(x, dd);
     38         }
     39         else
     40         {
     41             y->pushdown(), x->pushdown();
     42             d=y->c[1]==x;
     43             rotate(x, d);
     44         }
     45     x->maintain();
     46 }
     47 inline node * access(node * x) {node * y; for (y=null;x!=null;x=x->f) splay(x), x->c[1]=y, (y=x)->maintain(); return y;}
     48 inline void evert(node * x) {access(x)->rev^=1;}
     49 inline node * find(node * x) {for ( ;x->f!=null;x=x->f); return x;}
     50 inline void link(node * x, node * y) {evert(x); splay(x); x->f=y;}
     51 inline void cut(node * x, node * y) {evert(x); access(y); splay(y); y->c[0]=y->c[0]->f=null;}
     52 inline bool check(node * x, node * y) {return find(x)==find(y);}
     53 inline node * query(node * x, node * y) {evert(x); access(y); splay(y); return y->min;}
     54 
     55 struct seg {int cnt; seg * l, * r; inline seg():cnt(0) {l=r=this;}};
     56 seg * nul=new seg();
     57 seg memoryOfSeg[sizeOfPoint<<6], * portOfSeg=memoryOfSeg;
     58 seg * T[sizeOfPoint];
     59 inline seg * newseg(seg * t=nul) {seg * newt=portOfSeg++; if (t!=nul) newt->cnt=t->cnt, newt->l=t->l, newt->r=t->r; else newt->cnt=0, newt->l=nul, newt->r=nul; return newt;}
     60 seg * insert(seg * , int, int, int);
     61 
     62 inline void prepare();
     63 inline void build();
     64 inline int query(int, int);
     65 
     66 int main()
     67 {
     68     int lastans=0;
     69     int l, r;
     70 
     71     n=getint(); m=getint(); k=getint(); type=getint();
     72     for (int i=1;i<=m;i++) u[i]=getint(), v[i]=getint();
     73     prepare();
     74     build();
     75 
     76 
     77     for (int i=1;i<=k;i++)
     78     {
     79         l=getint(), r=getint();
     80         if (type) l^=lastans, r^=lastans;
     81         putint(lastans=query(l, r));
     82     }
     83 
     84     return 0;
     85 }
     86 inline int getint()
     87 {
     88     register int num=0;
     89     register char ch;
     90     do ch=getchar(); while (ch<'0' || ch>'9');
     91     do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9');
     92     return num;
     93 }
     94 inline void putint(int num)
     95 {
     96     char stack[10];
     97     register int top=0;
     98     if (num==0) stack[top=1]='0';
     99     for ( ;num;num/=10) stack[++top]=num%10+'0';
    100     for ( ;top;top--) putchar(stack[top]);
    101     putchar('
    ');
    102 }
    103 seg * insert(seg * t, int l, int r, int k)
    104 {
    105     seg * newt=newseg(t);
    106     newt->cnt++;
    107     if (l==r) return newt;
    108     int m=(l+r)>>1;
    109     if (k<=m) newt->l=insert(newt->l, l, m, k);
    110     else newt->r=insert(newt->r, m+1, r, k);
    111     return newt;
    112 }
    113 inline void prepare()
    114 {
    115     for (int i=1;i<=n;i++) t[i]=newnode(i);
    116     for (int i=0;i<=n;i++) time[i]=inf;
    117     for (int i=1, j=n+1;i<=m;i++, j++)
    118     {
    119         if (u[i]==v[i]) {ntr[i]=i; continue;}
    120         if (check(t[u[i]], t[v[i]]))
    121         {
    122             node * c=query(t[u[i]], t[v[i]]);
    123             ntr[i]=time[c->id];
    124             cut(t[u[i]], c); cut(t[v[i]], c);
    125         }
    126         t[j]=newnode(j); time[j]=i;
    127         link(t[u[i]], t[j]); link(t[v[i]], t[j]);
    128     }
    129 }
    130 inline void build()
    131 {
    132     T[0]=nul;
    133     for (int i=1;i<=m;i++)
    134         T[i]=insert(T[i-1], 0, m, ntr[i]);
    135 }
    136 inline int query(int x, int y)
    137 {
    138     seg * i=T[x-1], * j=T[y];
    139     int ret=0;
    140     int left=0, right=m, mid;
    141     for ( ;j!=nul; )
    142     {
    143         mid=(left+right)>>1;
    144         if (x>mid)
    145         {
    146             ret+=j->l->cnt-i->l->cnt;
    147             i=i->r, j=j->r;
    148             left=mid+1;
    149         }
    150         else
    151         {
    152             i=i->l, j=j->l;
    153             right=mid;
    154         }
    155     }
    156     return n-ret;
    157 }
    本傻莫名 T 出翔系列
  • 相关阅读:
    toj 2819 Travel
    toj 2807 Number Sort
    zoj 2818 Prairie dogs IV
    zoj 1276 Optimal Array Multiplication Sequence
    toj 2802 Tom's Game
    toj 2798 Farey Sequence
    toj 2815 Searching Problem
    toj 2806 Replace Words
    toj 2794 Bus
    css截取字符
  • 原文地址:https://www.cnblogs.com/dyllalala/p/3980373.html
Copyright © 2011-2022 走看看