【JZOJ 5433】【NOIP2017提高A组集训10.28】图

来源:互联网 发布:请假流程数据库设计 编辑:程序博客网 时间:2024/06/05 22:52

Description

有一个n个点A+B条边的无向连通图,有一变量x,每条边的权值都是一个关于x的简单多项式,其中有A条边的权值是k+x,另外B条边的权值是k-x,如果只保留权值形如k+x的边,那么这个图仍是一个连通图,如果只保留权值形如k-x的边,这个图也依然是一个连通图。
给出q组询问,每组询问给出x的值,问此时这个无向连通图的最小生成树权值是多少。

Solution

显然可以在原来的A条边中,只有只用A中的边构成的最小生成树的n-1条边是有用的,也就是A可以变成n-1,
那B条也一样,同理,

那么对于剩下的边,先假设x=,那么肯定是A中的边优,全选A的边,
随着x的增加,B中的边越来越优,逐渐替换掉的某些A边,

先把B按权值从小到大排序,(后边解释)
对于每条B边(x->y),找在生成树上,x,y这两个点经过的,权值最大的A边是哪条,那么就可以算出这条B边什么时候可以派上用场,
那如果我查询的这条路径上有几条是B边怎么办?
其实遇到B边是不用管的,因为我们已经按权值排序,所以你现在遇到的B边,一定比你先要派上用场,
这个用LCT即可,

最后,再看看每个询问,有多少个B边是派上用场的,

Code

#include <cstdio>#include <algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fod(i,a,b) for(int i=a;i>=b;i--)#define min(q,w) ((q)>(w)?(w):(q))#define max(q,w) ((q)<(w)?(w):(q))#define SD(q) (b[b[q].fa].r==(q))using namespace std;typedef long long LL;const int N=200500,INF=2147483640;int read(int &n){    char ch=' ';int q=0,w=1;    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());    if(ch=='-')w=-1,ch=getchar();    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;}int m,n,m1,m2;struct qwqw{    int x,y,v;}a[N],a1[N];struct inpu{    int x,i;}sc[N];struct TJtime{    int ti;    LL ans;}c[N];int c0;struct qqww{    int l,r,fa,si,FA;    int Rla,v,mx,mx1;    int bx,by;}b[N*4];int g[N];int b0;LL Ans[N],ans;bool PX(qwqw q,qwqw w){return q.v<w.v;}bool PXc(TJtime q,TJtime w){return q.ti<w.ti;}bool PXsc(inpu q,inpu w){return q.x<w.x;}int gf(int q){return g[q]==q?q:(g[q]=gf(g[q]));}void merge(int q){    b[q].si=b[b[q].l].si+b[b[q].r].si+1;    b[q].mx=b[q].v,b[q].mx1=q;    if(b[q].mx<b[b[q].l].mx)b[q].mx=b[b[q].l].mx,b[q].mx1=b[b[q].l].mx1;    if(b[q].mx<b[b[q].r].mx)b[q].mx=b[b[q].r].mx,b[q].mx1=b[b[q].r].mx1;}void doit(int q){    if(!b[q].Rla||!q)return;    swap(b[q].l,b[q].r);    if(b[q].l)b[b[q].l].Rla^=1;    if(b[q].r)b[b[q].r].Rla^=1;    b[q].Rla=0;}void rotate(int q){    int w=b[q].fa;    doit(w),doit(b[w].l),doit(b[w].r);    doit(q),doit(b[q].l),doit(b[q].r);    swap(b[w].FA,b[q].FA);    if(SD(q))    {        b[w].r=b[q].l;        b[b[q].l].fa=w;        b[q].l=w;    }else    {        b[w].l=b[q].r;        b[b[q].r].fa=w;        b[q].r=w;    }    if(SD(w))b[b[w].fa].r=q;    else b[b[w].fa].l=q;    b[q].fa=b[w].fa;    b[w].fa=q;    merge(w);    merge(q);}void Splay(int q,int T){    doit(q);    for(;b[q].fa!=T&&b[q].fa;)    {        if(b[b[q].fa].fa!=T&&b[b[q].fa].fa)        {            if(SD(q)==SD(b[q].fa))rotate(b[q].fa);            else rotate(q);        }        rotate(q);    }}void access(int q){    int q1=q,w;    for(w=q,q=0;w;q=w,w=b[w].FA)    {        Splay(w,0);        b[b[w].r].FA=w;        b[b[w].r].fa=0;        b[w].r=q;        b[q].FA=0;        b[q].fa=w;        merge(w);    }    Splay(q1,0);}void makeroot(int q){    access(q);    b[q].Rla=1;    doit(q);}void DLT(int q){    int x=b[q].bx,y=b[q].by;    makeroot(x);    access(y);    Splay(x,0);    Splay(y,x);    b[y].l=0;    b[q].l=b[q].r=b[q].fa=0;    b[y].fa=0;    b[x].r=0;    merge(y);    merge(x);}int main(){    freopen("graph.in","r",stdin);    freopen("graph.out","w",stdout);    int q,w,_;    read(n),read(m1),read(m2),read(_);    fo(i,1,m1)read(a[i].x),read(a[i].y),read(a[i].v);    fo(i,1,m2)read(a1[i].x),read(a1[i].y),read(a1[i].v);    fo(i,1,_)read(sc[i].x),sc[i].i=i;    sort(a+1,a+1+m1,PX);    sort(a1+1,a1+1+m2,PX);    sort(sc+1,sc+1+_,PXsc);    fo(i,1,n)g[i]=i;    b0=n;    fo(I,1,m1)    {        q=a[I].x,w=a[I].y;        int x=gf(q),y=gf(w);        if(x==y)continue;        g[x]=y;ans+=(LL)a[I].v;        makeroot(q);        makeroot(w);        b0++;        b[b0].FA=q;        b[b0].mx=b[b0].v=I;        b[b0].mx1=b0;        b[b0].bx=q;        b[b0].by=w;        b[w].FA=b0;    }    fo(i,1,n)g[i]=i;    fo(I,1,m2)    {        q=a1[I].x,w=a1[I].y;        int x=gf(q),y=gf(w);        if(x==y)continue;        g[x]=y;        makeroot(q);        access(w);        c[++c0].ti=(a1[I].v-a[b[w].mx].v)/2;        if(a1[I].v-a[b[w].mx].v>0)c[c0].ti++;        c[c0].ans=a1[I].v-a[b[w].mx].v;        DLT(b[w].mx1);         makeroot(q);        makeroot(w);        b0++;        b[b0].FA=q;        b[b0].mx=b[b0].v=0;        b[b0].mx1=b0;        b[b0].bx=q;        b[b0].by=w;        b[w].FA=b0;    }    sort(c+1,c+1+c0,PXc);    q=1;    fo(i,1,_)    {        for(;q<=c0&&c[q].ti<=sc[i].x;q++)ans+=c[q].ans;        Ans[sc[i].i]=ans+(LL)sc[i].x*(LL)(n-1-2*(q-1));    }    fo(i,1,_)printf("%lld\n",Ans[i]);    return 0;}
阅读全文
0 0
原创粉丝点击