wc2014 紫荆花之恋

来源:互联网 发布:淘宝联盟点击数佣金 编辑:程序博客网 时间:2024/04/27 13:52

替罪羊树套treap,动态点分治维护

我去,分治树连接出向下的边没改。。。。调了我3个小时,真是醉飞了。。。。。

#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>using namespace std;#define N 100010#define INF 1000000000const double Zy=0.85;int n,Root,tot,Sum,Now_root,Lim;long long Ans;struct Node{    int l,r,w,size,rnd;    long long v;}t[N*150];struct Edge{    int to,next,value;}edge[N*2],edge1[N*2];int head[N],Tot,head1[N],Tot1;int size[N],root[N],S_root[N],f[N],A[N],fa[N][100],Floor[N];long long dis[N][100];bool done[N],QQQ;queue<int> Q,E;queue<int> qq;inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}    return x*f;}int New_edgenum()    //First CK:Correct{    if(!E.empty())    {        int now=E.front();E.pop();        return now;    }    else return ++Tot1;}void Addedge(int u,int v,int w)   //First CK:Correct{    Tot++;edge[Tot].next=head[u];edge[Tot].to=v;edge[Tot].value=w;head[u]=Tot;    Tot++;edge[Tot].next=head[v];edge[Tot].to=u;edge[Tot].value=w;head[v]=Tot;}void Addedge1(int u,int v)   //First CK:Correct{    int now=New_edgenum();    edge1[now].next=head1[u];edge1[now].to=v;head1[u]=now;}void Rec_treap(int &k)   //First CK:Correct{    if(!k)return;    if(t[k].l)Rec_treap(t[k].l);    if(t[k].r)Rec_treap(t[k].r);    t[k].v=t[k].size=t[k].w=t[k].rnd=0;    Q.push(k);k=0;}int New_node()   //First CK:Correct{    if(!Q.empty())    {        int now=Q.front();Q.pop();        return now;    }    else return ++tot;}void Pushup(int k)     // First CK:Correct{    t[k].size=t[t[k].l].size+t[t[k].r].size+t[k].w;}void Left_rotate(int &k)   //First CK:Correct{    int tmp=t[k].r;t[k].r=t[tmp].l;t[tmp].l=k;    t[tmp].size=t[k].size;Pushup(k);k=tmp;}void Right_rotate(int &k)   //First CK:Correct{    int tmp=t[k].l;t[k].l=t[tmp].r;t[tmp].r=k;    t[tmp].size=t[k].size;Pushup(k);k=tmp;}void Insert(int &k,long long x)    //First CK:Correct{    if(!k)    {        k=New_node();t[k].v=x;t[k].size=t[k].w=1;        t[k].rnd=rand();return;    }    t[k].size++;    if(t[k].v==x)        t[k].w++;    else if(t[k].v>x)    {        Insert(t[k].l,x);        if(t[t[k].l].rnd<t[k].rnd)Right_rotate(k);    }    else    {        Insert(t[k].r,x);        if(t[t[k].r].rnd<t[k].rnd)Left_rotate(k);    }}int Query(int k,long long x)      //First CK:Correct{    if(!k)        return 0;    if(t[k].v==x)    {        return t[t[k].l].size+t[k].w;    }    else if(t[k].v>x)        return Query(t[k].l,x);    else return Query(t[k].r,x)+t[t[k].l].size+t[k].w;}void Find_root(int k,int last)   //First CK:Correct{    size[k]=1;f[k]=0;    for(int i=head[k];i;i=edge[i].next)    {        int v=edge[i].to;        if(done[v]||v==last)            continue;        Find_root(v,k);        size[k]+=size[v];        f[k]=max(f[k],size[v]);    }    f[k]=max(f[k],Sum-f[k]);    if(f[k]<f[Now_root])        Now_root=k;}void DFS(int k,int Fa,int rt,int floor){    Insert(root[rt],dis[k][floor]-A[k]);size[k]=1;    for(int i=head[k];i;i=edge[i].next)    {        int v=edge[i].to;        if(v==Fa||done[v])            continue;        dis[v][floor]=dis[k][floor]+edge[i].value;        fa[v][floor]=rt;        DFS(v,k,rt,floor);        size[k]+=size[v];    }}void Get_contribution(int k,int rt){    Insert(S_root[rt],dis[k][Floor[rt]-1]-A[k]);    for(int i=head1[k];i;i=edge1[i].next)    {        int v=edge1[i].to;        Get_contribution(v,rt);    }}void Work(int k,int floor){    done[k]=true;Floor[k]=floor;    fa[k][floor]=k;dis[k][floor]=0;    DFS(k,0,k,floor);    for(int i=head[k];i;i=edge[i].next)    {        int v=edge[i].to;        if(done[v]||!v)            continue;        Sum=size[v];Now_root=0;        Find_root(v,Now_root);        Addedge1(k,Now_root);        Work(Now_root,floor+1);    }    Get_contribution(k,k);}bool Balance(int k){    int Max=0;    for(int i=head1[k];i;i=edge1[i].next)    {        int v=edge1[i].to;        Max=max(Max,size[v]);    }    return Zy*size[k]>=Max;}void Rec(int k){    Rec_treap(root[k]);Rec_treap(S_root[k]);    for(int i=head1[k];i;i=edge1[i].next)    {        int v=edge1[i].to;        Rec(v);        E.push(i);    }    head1[k]=0;done[k]=0;}void Rebuild(int k){    int FFF=fa[k][Floor[k]-1];    for(int j=head1[FFF];j;j=edge1[j].next)    {        int v=edge1[j].to;        qq.push(v);        E.push(j);    }    head1[FFF]=0;    while(!qq.empty())    {        int now=qq.front();qq.pop();        if(now!=k)            Addedge1(FFF,now);    }    Rec(k);    Now_root=0;Sum=size[k];    Find_root(k,Now_root);    Addedge1(FFF,Now_root);    Work(Now_root,Floor[k]);}void My_insert(int Fa,int k,int value){    int Now_floor=Floor[Fa];Floor[k]=Now_floor+1;    fa[k][Floor[k]]=k;dis[k][Floor[k]]=0;    if(Fa!=0)    {Addedge(Fa,k,value);Addedge1(Fa,k);}    for(int i=Floor[k];i>=1;i--)    {        int pos;long long d;        if(i==Floor[k])            pos=k,d=0;        else  pos=fa[Fa][i],d=value+dis[Fa][i];        fa[k][i]=pos;dis[k][i]=d;        size[pos]++;        Insert(root[pos],d-A[k]);        if(i>1)        {            Ans+=Query(root[fa[Fa][i-1]],(long long)A[k]-value-dis[Fa][i-1]);            Ans-=Query(S_root[pos],(long long)A[k]-value-dis[Fa][i-1]);            Insert(S_root[pos],(long long)value+dis[Fa][i-1]-A[k]);        }    }    int sheep=0;    for(int i=Floor[k];i>=1;i--)    {        int now=fa[k][i];        if(!Balance(now))sheep=now;    }    if(sheep)Rebuild(sheep);}int main(){    int hehe=read();    n=read();f[0]=INF;    for(int i=1;i<=n;i++)        done[i]=true;    for(int i=1;i<=n;i++)    {        int x=read(),y=read();A[i]=read();        x^=(Ans%1000000000);        My_insert(x,i,y);        printf("%lld\n",Ans);    }    return 0;}


0 0
原创粉丝点击