NOI 十连测 Round 5 T1

SOL:

   这是一个很骚的构造。我们把一条无向边拆成2条有向边,并且定义一个点的点权为所有指向它的边的权之和。

那么我们发现,2*ans= A选的点权- B选的点权。

  当一边的两点被分别选时,其对答案的贡献为0,而在右边的柿子的贡献也为0,当被一个人选时,右式将其记了两次。

那么我们发现ans=sort(降序),simga a(奇数)-simga a(偶数)。

讲道理,数组写treap好蛋疼啊。

#include<bits/stdc++.h>
#define N 1000007
using namespace std;
inline int rop() {
    static int x=23333;
    return x^=x<<13,x^=x>>17,x^=x<<5;
}
struct Node{
    int son[2],key,val,siz,sum;
    Node() {}
    inline void pod(int x) {
       key=x;siz=1;sum=x;val=rop();son[0]=son[1]=0;
    }
    inline void pud();
}T[N];
#define M 100007
int root,a[M],k,x,y,z,tot,n,q,op,u[M],v[M],w[M],lastans,o,p;
inline void Node::pud() {
        siz=T[son[0]].siz+T[son[1]].siz+1;
        sum=T[son[0]].sum+(key-T[son[1]].sum)*((T[son[0]].siz&1)?-1:1);
}
#define sight(x) ('0'<=x&&x<='9')
inline void read(int &x){
    static char c;
    for (c=getchar();!sight(c);c=getchar());
    for (x=0;sight(c);c=getchar())x=x*10+c-48;
}
void write(int x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
inline void writeln(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('\n'); }
inline void writel(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); }
void split(int now,int k,int &x,int &y){
      if (!now) {x=y=0;return;}
      int cmp=T[T[now].son[0]].siz+1;
      if (cmp>k) y=now,split(T[y].son[0],k,x,T[y].son[0]); 
      else   x=now,split(T[x].son[1],k-cmp,T[x].son[1],y);
      T[now].pud(); 
}
int merge(int x,int y){
    if (!x||!y) return x+y;
    T[x].pud(); T[y].pud();
    if (T[x].val<T[y].val) 
    { T[x].son[1]=merge(T[x].son[1],y); T[x].pud(); return x;}
    T[y].son[0]=merge(x,T[y].son[0]); T[y].pud(); return  y;
}
inline int Kth(int x){
    static int rt,anw;
    rt=root; anw=0;
    while (rt) 
        if (T[rt].key<=x) rt=T[rt].son[0];
        else anw+=T[T[rt].son[0]].siz+1,rt=T[rt].son[1];  
    return anw;
} 
inline void ins(int X){
    if (!X) return;
    k=Kth(X);
    split(root,k,x,y); T[++tot].pod(X);
    root=merge(merge(x,tot),y);
} 
inline void del(int X){
    if (!X) return;
    k=Kth(X);
    split(root,k,x,y); split(y,1,y,z);
    root=merge(x,z);
}
int org;
signed main () {
    freopen("round.in","r",stdin);
    freopen("round.out","w",stdout);
    read(n); read(q); read(o);
    for (int i=1;i<=q;i++) {
      read(op);
      if (op) {
         read(u[++org]); read(v[org]); read(w[org]);
         u[org]^=o*lastans; v[org]^=o*lastans;
         del(a[u[org]]); 
         ins(a[u[org]]=a[u[org]]+w[org]);
         del(a[v[org]]); 
         ins(a[v[org]]=a[v[org]]+w[org]);
      }    else {
         read(p); p^=o*lastans;
         del(a[u[p]]); ins(a[u[p]]=a[u[p]]-w[p]);
         del(a[v[p]]); ins(a[v[p]]=a[v[p]]-w[p]);
      }
      writeln(lastans=(T[root].sum>>1));
    } 
    return 0;
}

 

posted @ 2018-03-27 21:30  泪寒之雪  阅读(196)  评论(0编辑  收藏  举报