jzoj5433. A set of training to improve NOIP2017 [10.28] FIG.

Description

A n points A + B no connected graph of edges, a variable x, the weight of each edge is a simple polynomial with respect to x, wherein A has the right sides is a value of k + x, B additionally weights of edges is kx, if only to retain the weight of the form k + edge x, then this figure remains a connected graph, if only to retain the weight of the form kx edge, this figure also remains a connected graph.
Given query q groups, each challenge value x is given, no Q at this time is the minimum weight spanning tree how to communicate with the FIG.

Input

A first n-number of row four, A, B, and q
Next A lines of three integers u, v, K, expressed between u and v is a weight to the k + x side without
subsequent B lines of three integers u, v, K, a weight value expressed kx undirected edges between u and v
Next q lines each an integer v, when x = v when asked FIG minimum generation how much weight tree

Output

Q total output lines, each line represents a number corresponding to the answer to the query

Sample Input

5 4 4 4
1 3 2
1 2 0
3 5 5
3 4 10
5 4 7
2 3 6
1 2 1000
3 4 1000
0
1
2
3

Sample Output

14
16
18
18

Data Constraint

For 30% of the data, \ (. 1 <= n-, Q <= 1000, n--. 1 <= A, B <= 2000 \)
for the other 20% of the data, all the weights of the form \ (k + x \) of side k satisfies, \ (0 <= k <= 10 ^. 8 \) , all the weights of the form kx sides k satisfies \ (. 9 * 10 ^. 8 <= k <= 10 ^. 9 \) , all inquiries v satisfies \ (0 <= v <=
4 * 10 ^ 8 \) for another 40% of the data, \ (. 1 <= n-<= 1000,1 <= Q <= 100000,. 1-n-<= a, B <2000 = \)
to 100% of the data, \ (. 1 <= n-, Q <= 100000,. 1-n-<= a, B <= 200000, 0 <= K <= 10. 9 ^, ^ -10. 9 < = v <= 10 ^ 9 \ )

Competitions

Nothing mind game, see there just playing 50 minutes, the brain will not last.
In fact, 100 is also very easy to think ah ~
Although the need to use LCT, but casual violence they also have 90 points up.
Blood loss.

answer

We found that there are certainly some cases, the minimum spanning tree of A, is also likely to B.
So we do both sides of the MST, and then to retain these sides, the other sides apparently could not.
Then we can find a magic stuff, when x becomes larger when A minimum spanning tree will gradually become a B.
As for how change is actually there is some minimum spanning tree is removed from the side A, side B is added.
Here Insert Picture Description
It can be found by drawing several figures, in fact, this process of change is as follows:
1, First, the k-edge of the B value in ascending order.
2, assuming the current to get the i th edge, this edge will be apparent then replace the current largest ring A side.
3, persimmon of what can be found, when x> (value P [i] is out of) P [i], the current i th sides can be replaced.
The above process can be used to maintain the LCT. (Of course, also be direct violence beautifully)
so we calculated for each edge in the x> can alternate when p [i].
A row order, each half can be asked.

Standard process

#include<cstdio>
#include<iostream>
using namespace std;
const int maxn=400010;

struct node{
    long long pf,fa,son[2],key,sum,tag,max,wz,val,id;
}t[maxn]; 

long long q,A,B,f[maxn],d[maxn],wz,zd,op,gs;
long long z[maxn*2],x[maxn*2],y[maxn*2],v,n,m,anss[maxn],answ[maxn],xx,answer[maxn];
long long ax[maxn],ay[maxn],az[maxn],jax[maxn],jay[maxn],jaz[maxn];
long long bx[maxn],by[maxn],bz[maxn],jbx[maxn],jby[maxn],jbz[maxn];

void make(int x)
{
    swap(t[x].son[0],t[x].son[1]);
    t[x].tag^=1;
}

void update(int x)
{
    t[x].sum=t[t[x].son[0]].sum+t[t[x].son[1]].sum+t[x].key;
    t[x].max=t[t[x].son[0]].max;t[x].wz=t[t[x].son[0]].wz;
    if (t[t[x].son[1]].max>t[x].max) 
    {
        t[x].max=t[t[x].son[1]].max;t[x].wz=t[t[x].son[1]].wz;
    }
    if (t[x].val>t[x].max)
    {
        t[x].max=t[x].val;t[x].wz=t[x].id;
    }
}

void clear(int x)
{
    if(t[x].tag)
    {
        make(t[x].son[0]),make(t[x].son[1]);
        t[x].tag=0;
    }
}

void remove(int x,int y)
{
    for (d[0]=0;x!=y;x=t[x].fa) d[++d[0]]=x;
    for (int i=d[0];i>=1;--i) clear(d[i]);
}

int get(int x)
{
    return t[t[x].fa].son[1]==x;
}

void rotate(int x)
{
    int y=t[x].fa,k=get(x);
    if(t[y].fa) t[t[y].fa].son[get(y)]=x;
    if(t[x].son[!k]) t[t[x].son[!k]].fa=y;
    t[y].son[k]=t[x].son[!k],t[x].fa=t[y].fa,t[y].fa=x,t[x].son[!k]=y;
    update(y),update(x),t[x].pf=t[y].pf;
}

void splay(int x,int y)
{
    remove(x,y);
    while(t[x].fa!=y)
    {
        if(t[t[x].fa].fa!=y)
            if(get(x)==get(t[x].fa)) rotate(t[x].fa);
            else rotate(x);
        rotate(x);
    }
}

void access(int x)
{
    for (int y=0;x;update(x),y=x,x=t[x].pf)
    {
        splay(x,0);
        t[t[x].son[1]].fa=0,t[t[x].son[1]].pf=x;
        t[x].son[1]=y,t[y].fa=x,t[y].pf=0;
    }
}

int findroot(int x)
{
    access(x),splay(x,0);
    for (;t[x].son[0];x=t[x].son[0]);
    return x;
}

void makeroot(int x)
{
    access(x),splay(x,0);
    make(x);
}

void query(int x,int y)
{
    makeroot(x),access(y);
    splay(y,0);
    wz=t[y].wz;
    zd=t[y].max;
}

void link(int x,int y)
{
    makeroot(x);
    if(findroot(y)!=x) t[x].pf=y;
}

void cut(int x,int y)
{
    makeroot(x),access(y),splay(y,0);
    if(t[x].fa==y) t[y].son[get(x)]=t[x].fa=t[x].pf=0;
}

void change(int x,int y)
{
    splay(x,0);
    t[x].key=y,update(x);
}

int getfather(int x)
{
    if (f[x]==x) return x;
    f[x]=getfather(f[x]);
    return f[x];
}

void qsort(int l,int r)
{
    int i=l;int j=r;
    long long m=z[(i+j)/2];
    while (i<=j)
    {
        while (z[i]<m) i++;
        while (z[j]>m) j--;
        if (i<=j)
        {
            swap(z[i],z[j]);
            swap(x[i],x[j]);
            swap(y[i],y[j]);
            i++;j--;
        }
    }
    if (l<j) qsort(l,j);
    if (r>i) qsort(i,r); 
}

void qsort1(int l,int r)
{
    int i=l;int j=r;
    long long m=anss[(i+j)/2];
    while (i<=j)
    {
        while (anss[i]<m) i++;
        while (anss[j]>m) j--;
        if (i<=j)
        {
            swap(anss[i],anss[j]);
            swap(answ[i],answ[j]);
            i++;j--;
        }
    }
    if (l<j) qsort1(l,j);
    if (r>i) qsort1(i,r); 
}

int main()
{
    freopen("graph.in","r",stdin);
    freopen("graph.out","w",stdout);
    scanf("%d%d%d%d",&n,&A,&B,&m);
    for (int i=0;i<=n;i++)
    {
        t[i].val=-1000000000000;t[i].key=0;t[i].max=t[i].val;
    }
    for (int i=1;i<=A;i++) scanf("%lld%lld%lld",&ax[i],&ay[i],&az[i]);
    for (int i=1;i<=B;i++) scanf("%lld%lld%lld",&bx[i],&by[i],&bz[i]);
    
    int gs=0;
    for (int i=1;i<=A;i++)
    {
        gs++;
        x[gs]=ax[i];y[gs]=ay[i];z[gs]=az[i];
    }
    qsort(1,gs);
    for (int i=1;i<=n;i++) f[i]=i;
    for (int i=1;i<=gs;i++)
    {
        int xx=getfather(x[i]);
        int yy=getfather(y[i]);
        if (xx!=yy)
        {
            f[xx]=yy;
            op++;
            jax[op]=x[i];jay[op]=y[i];jaz[op]=z[i];
            t[op+n].id=op;t[op+n].val=z[i];t[op+n].key=z[i];t[op+n].max=t[op+n].val;
            anss[0]+=z[i]; 
        }
    }
    
    for (int i=1;i<=op;i++)
    {
        link(jax[i],i+n);
        link(i+n,jay[i]);
    }
    makeroot(1);
    
    gs=0;
    for (int i=1;i<=B;i++)
    {
        gs++;
        x[gs]=bx[i];y[gs]=by[i];z[gs]=bz[i];
    }
    qsort(1,gs);
    for (int i=1;i<=n;i++) f[i]=i;
    int pp=0;
    for (int i=1;i<=gs;i++)
    {
        int xx=getfather(x[i]);
        int yy=getfather(y[i]);
        if (xx!=yy)
        {
            if (i==135)
            {
                int j=0;
            }
            f[xx]=yy;
            op++;pp++;
            jbx[op]=x[i];jby[op]=y[i];jbz[op]=z[i];
            query(x[i],y[i]);
            anss[pp]=z[i]-jaz[wz];
            if ((z[i]-jaz[wz])%2==1) answ[pp]=(z[i]-jaz[wz])/2+1; else answ[pp]=(z[i]-jaz[wz])/2;
            cut(jax[wz],n+wz);cut(n+wz,jay[wz]);
            t[op+n].id=op;t[op+n].val=-1000000000000;t[op+n].key=z[i];t[op+n].max=t[op+n].val;
            link(x[i],op+n);link(op+n,y[i]);
        }
    }
    
    qsort1(1,n-1);
    
    answer[0]=anss[0];
    for (int i=1;i<n;i++)
    {
        answer[i]=anss[i]+answer[i-1];
    }
    
    for (int i=1;i<=m;i++)
    {
        scanf("%lld",&xx);
        int l=1;int r=n-1;int k=0;
        while (l<=r)
        {
            int mid=(l+r)/2;
            if (xx>=answ[mid])
            {
                k=mid;
                l=mid+1;
            }
            else r=mid-1;
        }
        printf("%lld\n",answer[k]+(n-1-2*k)*xx);
    }
} 

Guess you like

Origin www.cnblogs.com/RainbowCrown/p/11593263.html