codechef October Challenge 2017解题报告

来源:互联网 发布:江南大学网络教育2017 编辑:程序博客网 时间:2024/06/03 17:10

第二次打challenge。。果然还是拿不到钱(艹不过大佬)啊。

A Balanced Contest

模拟就好。

#include <bits/stdc++.h>#define gc getchar()#define ll long longusing namespace std;int read(){    int x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    int s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return x*s;}int main(){    int T=read();    while (T--)    {        int n=read(),p=read(),a=0,b=0;        for (int i=1;i<=n;i++)        {            int x=read();            if (x>=p/2) a++;            if (x<=p/10) b++;        }        if (a==1&&b==2) puts("yes");        else puts("no");    }    return 0;}

Max Mex

题意很脑残,写法很简单。

#include <bits/stdc++.h>#define gc getchar()#define ll long long#define N 1000009using namespace std;int a[N];int read(){    int x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    int s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return x*s;}int main(){    int T=read();    while (T--)    {        int n=read(),k=read();        memset(a,0,sizeof(a));        for (int i=1;i<=n;i++) a[read()]=1;        int ans=0;        for (int i=1;i<=k;i++)        {            while (a[ans]==1) ans++;            a[ans]=1;        }        while (a[ans]==1) ans++;        printf("%d\n",ans);    }    return 0;}

Counter Test For CHEFSUM

构造题,卡了我好久啊。

#include <bits/stdc++.h>#define gc getchar()#define ll long long#define mod 4294967296llusing namespace std;ll read(){    ll x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    ll s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return x*s;}int main(){    ll T=read();    while (T--)    {        ll n=read();        ll b=(mod-1)/(n-1);        ll c=(mod-1-b*(n-1))/2;        if (c>b) c+=mod-(b*(n-1)+2*c);        //cout<<b<<" "<<c<<endl;        for (ll i=1;i<=n;i++)            printf("%lld%s",(i==1)?c:b,(i==n)?"\n":" ");    }    return 0;}

Chef and a great voluntary Program

贪心好(差)题。
不要被卡题意是快速AC的关键。(雾)

#include <bits/stdc++.h>#define gc getchar()#define ll long long#define N 100009using namespace std;int n,a,b,x,y;char str[N];int read(){    int x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    int s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return x*s;}int main(){    int T=read();    while (T--)    {        scanf("%s",str+1);        n=strlen(str+1),a=b=0;        for (int i=1;i<=n;i++)            if (str[i]=='a') a++;            else b++;        x=read(),y=read();        int num1=a/x,num2=b/y,ans1=0,ans2=0;        if (a%x) num1++;        if (b>=num1-1) ans1=0;        else ans1=a-b*x-x;        if (b%y) num2++;        if (a>=num2-1) ans2=0;        else ans2=b-a*y-y;        if (num1*y>=b&&!ans1)        {            int c=b/num1+1,d=b/num1;            int c_num=b%num1,d_num=num1-c_num;            assert(c*c_num+d*d_num==b);            assert((c<=y)||(c_num==0&&c==y+1));            for (int i=1;i<=c_num;i++)            {                for (int j=1;j<=x;j++) putchar('a');                for (int j=1;j<=c;j++) putchar('b');                a-=x;            }            for (int i=1;i<=d_num;i++)            {                for (int j=1;j<=min(a,x);j++) putchar('a');                for (int j=1;j<=d;j++) putchar('b');                a-=min(a,x);            }            assert(a==0);        }        else            if (num2*x>=a&&!ans2)            {                int c=a/num2+1,d=a/num2;                int c_num=a%num2,d_num=num2-c_num;                assert(c*c_num+d*d_num==a);                assert((c<=x)||(c_num==0&&c==x+1));                for (int i=1;i<=c_num;i++)                {                    for (int j=1;j<=y;j++) putchar('b');                    for (int j=1;j<=c;j++) putchar('a');                    b-=y;                }                for (int i=1;i<=d_num;i++)                {                    for (int j=1;j<=min(b,y);j++) putchar('b');                    for (int j=1;j<=d;j++) putchar('a');                    b-=min(b,y);                }                assert(b==0);            }            else                if (a>b)                {                    while (b--)                    {                        for (int i=1;i<=x;i++) putchar('a');                        putchar('b');                        a-=x;                    }                    assert(a>=0);                    for (int i=1;i<=a;i++)                    {                        if (i!=1&&(i-1)%x==0) putchar('*');                        putchar('a');                    }                }                else                {                    while (a--)                    {                        for (int i=1;i<=y;i++) putchar('b');                        putchar('a');                        b-=y;                    }                    assert(b>=0);                    for (int i=1;i<=b;i++)                    {                        if (i!=1&&(i-1)%y==0) putchar('*');                        putchar('b');                    }                }        puts("");    }    return 0;}

Chef and Cycled Cycles

一开始看成加强版,后来发现无脑前缀和就好了。

#include <bits/stdc++.h>#define gc getchar()#define ll long long#define N 200009using namespace std;int n,q,len[N],st[N],ed[N],val[N],sum[N],sv[N];vector<int> s[N];int read(){    int x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    int s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return x*s;}int Dis(int x,int y,int w){    if (y>w) swap(y,w);    return min(s[x][w-1]-s[x][y-1],s[x][len[x]]-(s[x][w-1]-s[x][y-1]));}int main(){    int T=read();    while (T--)    {        n=read(),q=read(),sum[0]=sv[0]=0;        for (int i=1;i<=n;i++)        {            s[i].resize(1+(len[i]=read()));            for (int j=0;j<=len[i];j++) s[i][j]=0;            for (int j=1;j<=len[i];j++)                s[i][j]=s[i][j-1]+read();        }        for (int i=1;i<=n;i++)            ed[i]=read(),st[i%n+1]=read(),sv[i]=sv[i-1]+read();        for (int i=1;i<=n;i++)            sum[i]=sum[i-1]+Dis(i,st[i],ed[i]);        while (q--)        {            int y=read(),x=read(),w=read(),z=read();            if (x>z) swap(x,z),swap(y,w);            int ans1=sum[z-1]-sum[x]+sv[z-1]-sv[x-1]+Dis(x,y,ed[x])+Dis(z,w,st[z]);            int ans2=sum[n]-(sum[z]-sum[x-1])+sv[n]-(sv[z-1]-sv[x-1])+Dis(x,y,st[x])+Dis(z,w,ed[z]);            printf("%d\n",min(ans1,ans2));        }    }    return 0;}

Chef and Magic Arrays

|x|=max(x,x)

然后就统计出正负两个最大的那个各转移一下就好啦。

#include <bits/stdc++.h>#define gc getchar()#define ll long long#define N 1000009#define inf (ll)1e18using namespace std;ll n,len[N],dp[N],M1,M2;vector<ll> a[N];ll read(){    ll x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    ll s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return x*s;}int main(){    ll T=read();    while (T--)    {        n=read();        for (ll i=1;i<=n;i++)        {            a[i].resize(len[i]=read());            for (ll j=0;j<len[i];j++) a[i][j]=read();        }        for (ll i=0;i<len[1];i++)            dp[i]=0;        ll Ans=0;        for (ll i=1;i<n;i++)        {            M1=-inf,M2=-inf;            for (ll j=0;j<len[i];j++)            {                M1=max(M1,dp[j]+i*a[i][j]);                M2=max(M2,dp[j]-i*a[i][j]);            }            for (ll j=0;j<len[i+1];j++)                dp[j]=max(M1-i*a[i+1][(j+1)%len[i+1]],M2+i*a[i+1][(j+1)%len[i+1]]);        }        for (ll i=0;i<len[n];i++)            Ans=max(Ans,dp[i]);        printf("%lld\n",Ans);    }    return 0;}

Shooting on the array

线段树维护好题。(可能分块也可以过)
跟bzoj上的楼房重建思想没什么区别,主要就是一个calc函数。
calc:在这个区间左边放一个高度x的柱子后,激光能射到几根柱子。

#include <bits/stdc++.h>#define gc getchar()#define ll long long#define N 1000009#define root 1,1,n#define mid (l+r>>1)#define lc cur<<1#define rc lc|1#define lson lc,l,mid#define rson rc,mid+1,r#define now cur,l,rusing namespace std;int n,q,a[N],Max[N<<2],Ans[N<<2];int read(){    int x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    int s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return x*s;}int calc(int cur,int l,int r,int x){    if (l==r) return Max[cur]>x;    if (Max[cur]<=x) return 0;    if (Max[lc]<=x) return calc(rson,x);    else return Ans[cur]-Ans[lc]+calc(lson,x);}void ins(int cur,int l,int r,int x,int y){    if (l==r)    {        Max[cur]+=y;        return;    }    if (x<=mid) ins(lson,x,y);    else ins(rson,x,y);    Ans[cur]=Ans[lc]+calc(rson,Max[lc]);    Max[cur]=max(Max[lc],Max[rc]);}void build(int cur,int l,int r){    if (l==r)    {        Max[cur]=a[l];        Ans[cur]=1;        return;    }    build(lson);    build(rson);    Ans[cur]=Ans[lc]+calc(rson,Max[lc]);    Max[cur]=max(Max[lc],Max[rc]);}int Lim(int cur,int l,int r,int L,int R,int x){    if (l==r)    {        if (Max[cur]>=x) return Max[cur];        else return 0;    }    if (L<=l&&R>=r)    {        if (Max[cur]>=x)        {            if (Max[lc]>=x) return Lim(lson,L,R,x);            else return Lim(rson,L,R,x);        }        else return 0;    }    if (L<=mid)    {        int tmp=Lim(lson,L,R,x);        if (tmp>=x) return tmp;    }    if (R>mid)    {        int tmp=Lim(rson,L,R,x);        if (tmp>=x) return tmp;    }    return 0;}int Ma;int qry(int cur,int l,int r,int L,int R){    if (L<=l&&R>=r)    {        int tmp=calc(now,Ma);        Ma=max(Ma,Max[cur]);        return tmp;    }    int ret=0;    if (L<=mid) ret=qry(lson,L,R);    if (R>mid) ret+=qry(rson,L,R);    return ret;}int main(){    int T=read();    while (T--)    {        n=read(),q=read();        for (int i=1;i<=n;i++) a[i]=read();        build(root);        while (q--)        {            char ch;            while (ch=gc,ch!='?'&&ch!='+');            if (ch=='?')            {                int i=read(),l=read(),r=read();                int lim=Lim(root,i,n,r);                if (lim)                {                    Ma=l-1;                    int ans1=qry(root,i,n);                    Ma=lim;                    int ans2=qry(root,i,n);                    printf("%d\n",ans1-ans2);                }                else                {                    Ma=l-1;                    int ans1=qry(root,i,n);                    printf("%d\n",ans1);                }            }            else            {                int x=read(),y=read();                ins(root,x,y);            }        }    }    return 0;}

Lucky Edge

这道题告诉我们,只要有信仰,卡常数暴力是可以过的。

#include <bits/stdc++.h>#define gc getchar()#define ll long long#define N 10009using namespace std;int n,m,first[N],number,dy[N],id[N],used[N],Ans[N],fa[N],pnt[N];int deep[N],q[N],to[N],sta[N],top,rk[N],head,tail,a[N],b[N];int t[N],nxt[N],v[N];int find(int x){    return fa[x]==x?x:fa[x]=find(fa[x]);}int read(){    int x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    int s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return x*s;}void bfs(int x){    head=1,tail=0;    q[++tail]=x;    pnt[x]=0;    while (head<=tail)    {        x=q[head++];        for (register int i=first[x];i;i=nxt[i])            if (t[i]!=pnt[x])            {                pnt[t[i]]=x;                q[++tail]=t[i];                deep[t[i]]=deep[x]+1;                to[t[i]]=v[i];            }    }}int main(){    int T=read(),x,y;    while (T--)    {        m=read();        n=0;        memset(dy,0,sizeof(dy));        memset(Ans,0,sizeof(Ans));        for (register int i=1;i<=m;i++)        {            x=read();            y=read();            if (!dy[x]) dy[x]=++n;            if (!dy[y]) dy[y]=++n;            a[i]=dy[x],b[i]=dy[y];        }        for (register int l=1;l<=m;l++)        {            number=1;            for (register int i=1;i<=n;i++)            {                rk[i]=first[i]=pnt[i]=0;                fa[i]=i;            }            for (register int i=l;i<=m;i++)            {                used[i]=0;                x=find(a[i]);                y=find(b[i]);                if (x!=y)                {                    if (rk[x]>rk[y]) swap(x,y);                    used[i]=1;                    fa[x]=y;                    if (rk[x]==rk[y]) rk[y]++;                    t[++number]=b[i];                    nxt[number]=first[a[i]];                    v[number]=i;                    first[a[i]]=number;                    t[++number]=a[i];                    nxt[number]=first[b[i]];                    v[number]=i;                    first[b[i]]=number;                }            }            for (register int i=1;i<=n;i++)            {                if (!pnt[i]) bfs(i);                fa[i]=i;            }            for (register int i=l;i<=m;i++)            {                if (used[i]) continue;                x=find(a[i]);                y=find(b[i]);                top=0;                while (x!=y)                {                    if (deep[x]<deep[y]) swap(x,y);                    Ans[to[x]]+=m-i+1;                    sta[++top]=x;                    x=find(pnt[x]);                }                Ans[i]+=m-i+1;                while (top) fa[sta[top--]]=x;            }        }        for (int i=1;i<=m;i++) printf("%d%s",Ans[i],i==m?"\n":" ");    }    return 0;}

Chef and Horcrux

这道题先算出答案为某个值x的概率px,然后就是k进制下的FWT即可。然后考虑如何trans,发现k个数配个系数就好,然后发现系数就是k次单位根,然后就没了。。(模数原根为22)

#include <bits/stdc++.h>#define gc getchar()#define ll long long#define N 1000009#define mod 330301441#define M 11using namespace std;int n,k,p[N],num[N],INV,w[2][N];ll x;int ksm(int x,ll y,int mo=mod,int ret=1){    for (;y;y>>=1ll,x=(ll)x*x%mo) if (y&1ll) ret=(ll)ret*x%mo;    return ret;}int inv(int x){    return ksm(x,mod-2);}int read(){    int x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    int s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return x*s;}ll Read(){    ll x=1;    char ch;    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;    ll s=ch-'0';    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';    return x*s;}void init(int &n){    int ret=1;    for (;ret<=n;ret*=k);    n=ret;    int G=ksm(22,(mod-1)/k);    w[0][0]=w[0][k]=w[1][0]=w[1][k]=1;    for (int i=1;i<k;i++) w[0][i]=(ll)w[0][i-1]*G%mod;    for (int i=1;i<k;i++) w[1][i]=w[0][k-i];}ll b[M];void FWT(int a[],int n){    for (int d=1;d<n;d*=k)        for (int m=d*k,i=0;i<n;i+=m)            for (int j=0;j<d;j++)            {                for (int l=0;l<k;l++)                {                    b[l]=0;                    for (int r=0;r<k;r++)                        b[l]=b[l]+(ll)a[i+j+d*r]*w[0][l*r%k];                }                for (int l=0;l<k;l++)                    a[i+j+d*l]=b[l]%mod;            }}void UFWT(int a[],int n){    for (int d=1;d<n;d*=k)        for (int m=d*k,i=0;i<n;i+=m)            for (int j=0;j<d;j++)            {                for (int l=0;l<k;l++)                {                    b[l]=0;                    for (int r=0;r<k;r++)                        b[l]=b[l]+(ll)a[i+j+d*r]*w[1][l*r%k];                }                for (int l=0;l<k;l++)                    a[i+j+d*l]=b[l]%mod;            }    for (int i=0;i<n;i++) a[i]=(ll)a[i]*INV%mod;}int main(){    int T=read();    while (T--)    {        n=read(),k=read(),x=Read();        for (int i=0;i<=100000;i++) num[i]=0;        memset(p,0,sizeof(p));        for (int i=1;i<=n;i++) num[read()]++;        int sum=1,rest=n;        int m=0;        for (int i=0;i<=100000;i++)        {            rest-=num[i];            p[i]=(ll)sum*ksm(2,rest)%mod;            p[i]=(ll)p[i]*inv(ksm(2,n))%mod;            sum=(ll)sum*(ksm(2,num[i])-1)%mod;            if (p[i]) m=i;        }        init(m);        INV=inv(m);        FWT(p,m);        for (int i=0;i<m;i++) p[i]=ksm(p[i],x);        UFWT(p,m);        int Ans=0;        for (int i=0;i<m;i++)            Ans=(Ans+(ll)ksm(p[i],3*i)*ksm(i,2*i)%mod)%mod;        printf("%d\n",Ans);    }    return 0;}

(Challenge) Connecting computers

到最后还是只有91分啊。。果然技不如人。。
题意就是给一张无向图,告诉你连边(i,j)代价C[i][j],某个点i度数为j的代价H[i][j]。让你在保证图联通的情况下,最小化代价。
考虑给每个点一个度数(度数代价最小的度数),然后尽量去满足,边从小到大加入,这样的话,最后可能不连通,然后就用用最小的代价合并连通块。然后主要就是调试参数(度数上限,加边上限)和加优化(三个点换边,四个点换边等等)。
似乎这样就有90分了。(但还是不懂100分的大佬是怎么搞得啊)

#include <bits/stdc++.h>#define ull unsigned long long#define ll long long#define N 1002#define M 1000009#define int_inf 1000000000#define ll_inf 1000000000000000000ll#define rep(a,b,c) for(int a = b;a <= c;a++)#define REP(a,b,c) for(int a = b;a <  c;a++)#define per(a,b,c) for(int a = b;a >= c;a--)#define PER(a,b,c) for(int a = b;a >  c;a--)#define debug 1using namespace std;int First[N],Number,ss[N],used[N];struct Edge{    int to,next;    void add(int x,int y)    {        to=y,next=First[x],First[x]=Number;    }}E[N*N];struct edge{    int x,y,z;    bool operator <(const edge &rhs) const    {        return z<rhs.z;    }}e[N*N],g[N*N];int C[N][N],H[N][N],fa[N],Ans[N][N],ans[N][N];int S,B,L,g_number,del_number,c[N][N],h[N][N];int n,Cmax,Hmax,number,d[N],D[N];int A[5],id,Min[5],Max[5];ll Mi_Ans,Mi_pos,res;char ch[N][N];bool vis[N][N];ull s[2];ull xorshift128plus(){    ull x=s[0];    const ull y=s[1];    x^=x<<23;    s[1]=x^y^(x>>17)^(y>>26);    return s[0]= y;}struct node{    int x,dis;    bool operator <(const node &rhs) const    {        return dis<rhs.dis;    }    node(int x=0,int dis=0):x(x),dis(dis){}};struct Node{    int x,y;    bool operator <(const Node &rhs) const    {        return x<rhs.x||x==rhs.x&&y<rhs.y;    }};struct circle{    int x,y,z,val;    bool operator <(const circle &rhs) const    {        return val<rhs.val;    }}del[N];unsigned long rng(unsigned long e = 0){    static unsigned long t = 0, x = 123456789, y = 362436069, z = 521288629, w = 88675123, v = 5783321, d = 6615241;    d += e; x += d; t = (x ^ (x >> 2)); x = y; y = z; z = w; w = v; v = (v ^ (v << 4)) ^ (t ^ (t << 1));    return e ? (((d += 362437) + v) % e) : ((d += 362437) + v);}struct EulerTourTree {    struct node {        node *lch = nullptr;        node *rch = nullptr;        node *parent = nullptr;        unsigned int size = 1;        int vid;        bool active = false;        unsigned int sub = 0;        node(int vid) : vid(vid) {}    };    unsigned int size(node *x) {        return x != nullptr ? x->size : 0;    }    unsigned int sub(node *x) {        return x != nullptr ? x->sub : 0;    }    node *update(node *x) {        if (x == nullptr) return x;        x->size = 1 + size(x->lch) + size(x->rch);        x->sub = sub(x->lch) + sub(x->rch);        if (x->active) x->sub++;        return x;    }    void update_ancestor(node *x) {        if (x == nullptr) return;        x = update(x);        update_ancestor(x->parent);    }    void activate(node *x, bool value) {        if (x == nullptr) return;        x->active = value;        update_ancestor(x);    }    node *merge(node *x, node *y) {        if (x == nullptr) return y;        if (y == nullptr) return x;        if (rng() % (size(x) + size(y)) < size(x)) {            x->rch = merge(x->rch, y);            if (x->rch != nullptr) x->rch->parent = x;            return update(x);        } else {            y->lch = merge(x, y->lch);            if (y->lch != nullptr) y->lch->parent = y;            return update(y);        }    }    pair<node *, node *> split(node *x, unsigned k) {        if (x == nullptr) return make_pair(nullptr, nullptr);        if (k <= size(x->lch)) {            auto p = split(x->lch, k);            x->lch = p.second;            if (p.first != nullptr) p.first->parent = nullptr;            if (p.second != nullptr) p.second->parent = x;            return make_pair(p.first, update(x));        } else {            auto p = split(x->rch, k - size(x->lch) - 1);            x->rch = p.first;            if (p.first != nullptr) p.first->parent = x;            if (p.second != nullptr) p.second->parent = nullptr;            return make_pair(update(x), p.second);        }    }    node *root(node *x) {        if (x == nullptr) return x;        if (x->parent == nullptr) return x;        return root(x->parent);    }    int index_of(node *x) {        if (x == nullptr) return 0;        int result = -1;        bool l = true;        while (x != nullptr) {            if (l) result += 1 + size(x->lch);            if (x->parent == nullptr) break;            l = x->parent->rch == x;            x = x->parent;        }        return result;    }    void connected_component(node *x, vector<int> &res) {        if (x == nullptr) return;        if (x->active) res.push_back(x->vid);        connected_component(x->lch, res);        connected_component(x->rch, res);    }    vector<int> connected_component(int u) {        node *x = root(any_node(u));        if (x == nullptr) return{ u };        vector<int> res;        connected_component(x, res);        return res;    }    vector<map<int, node *>> tr;    EulerTourTree(int n) : tr(n) {}    node *any_node(int u) {        return tr[u].empty() ? nullptr : tr[u].begin()->second;    }    bool link(int u, int v) {        node *x = any_node(u);        node *y = any_node(v);        node *root_x = root(x);        node *root_y = root(y);        if (root_x != nullptr && root_x == root_y) return false;        node *A, *B, *C, *D;        tie(A, B) = split(root_x, index_of(x));        tie(C, D) = split(root_y, index_of(y));        // AB, CD => A (u->v) D C (v->u) B        node *uv = new node(u);        node *vu = new node(v);        if (tr[u].empty()) activate(uv, true);        if (tr[v].empty()) activate(vu, true);        tr[u][v] = uv;        tr[v][u] = vu;        A = merge(A, uv);        A = merge(A, D);        A = merge(A, C);        A = merge(A, vu);        A = merge(A, B);        return true;    }    bool cut(int u, int v) {        if (tr[u].count(v) == 0) return false;        node *uv = tr[u][v];        node *vu = tr[v][u];        tr[u].erase(v);        tr[v].erase(u);        if (uv->active) {            activate(uv, false);            activate(any_node(u), true);        }        if (vu->active) {            activate(vu, false);            activate(any_node(v), true);        }        node *rt = root(uv);        int index_uv = index_of(uv);        int index_vu = index_of(vu);        if (index_uv > index_vu) swap(index_uv, index_vu);        node *A, *B;        auto p = split(rt, index_vu);        B = split(p.second, 1).second;        auto q = split(p.first, index_uv);        A = q.first;                 split(q.second, 1);        merge(B, A);        return true;    }    bool is_connected(int u, int v) {        if (u == v) return true;        node *x = any_node(u);        node *y = any_node(v);        return x != nullptr && root(x) == root(y);    }    int sub(int u) {        node *x = any_node(u);        if (x == nullptr) return 1;        return sub(root(x));    }};struct HolmDeLichtenbergThorup {    static const int L = 20;    vector<EulerTourTree> et;    vector<vector<set<int>>> g;    vector<vector<set<int>>> gg;    HolmDeLichtenbergThorup(int n) :        et(L, EulerTourTree(n)),        g(L, vector<set<int>>(n)),        gg(L, vector<set<int>>(n)) {}    bool insert(int u, int v) {        if (!et[0].is_connected(u, v)) {            assert(et[0].link(u, v));            gg[0][u].insert(v);            gg[0][v].insert(u);            return true;        } else {            g[0][u].insert(v);            g[0][v].insert(u);            return false;        }    }    bool erase(int u, int v) {        bool is_tree = false;        int level = -1;        for (int i = 0; i < L && level == -1; i++) {            et[i].cut(u, v);            if (gg[i][u].count(v) == 1) {                gg[i][u].erase(v);                gg[i][v].erase(u);                level = i;                is_tree = true;            }            if (g[i][u].count(v) == 1) {                g[i][u].erase(v);                g[i][v].erase(u);                level = i;            }        }        assert(level != -1);        if (!is_tree) return false;        return reconnect(level, u, v);    }    bool reconnect(int level, int u, int v) {        if (level == -1) return true;        int size_u = et[level].sub(u);        int size_v = et[level].sub(v);        if (size_u > size_v) swap(u, v);        vector<int> cc = et[level].connected_component(u);        for (int x : cc) {            auto &st = gg[level][x];            for (auto it = st.begin(); it != st.end();) {                int y = *it;                st.erase(it++);                gg[level][y].erase(x);                gg[level + 1][x].insert(y);                gg[level + 1][y].insert(x);                assert(et[level + 1].link(x, y));            }        }        for (int x : cc) {            auto &st = g[level][x];            for (auto it = st.begin(); it != st.end();) {                int y = *it;                if (et[level].is_connected(y, v)) {                    st.erase(it++);                    g[level][y].erase(x);                    gg[level][x].insert(y);                    gg[level][y].insert(x);                    for (int i = 0; i <= level; i++) {                        assert(et[i].link(x, y));                    }                    return false;                } else {                    st.erase(it++);                    g[level][y].erase(x);                    g[level + 1][x].insert(y);                    g[level + 1][y].insert(x);                }            }        }        return reconnect(level - 1, u, v);    }    bool is_connected(int u, int v) {        return et[0].is_connected(u, v);    }    int size_connected_component(int u) {        return et[0].sub(u);    }} ;void Atoa(){    for (int i=0;i<n;i++)        for (int j=0;j<n;j++) ans[i][j]=Ans[i][j];}void atoA(){    for (int i=0;i<n;i++)        for (int j=0;j<n;j++) Ans[i][j]=ans[i][j];}int find(int x){    return fa[x]==x?x:fa[x]=find(fa[x]);}void print(){    for (int i=0;i<n;i++)    {        for (int j=0;j<n;j++) printf("%d",Ans[i][j]);        puts("");    }}ll Get(){    ll ret=0;    for (int i=0;i<n;i++)    {        for (int j=i+1;j<n;j++)            if (Ans[i][j]) ret+=(ll)C[i][j];        int x=0;        for (int j=0;j<n;j++)            if (Ans[i][j]) x++;        ret+=(ll)H[i][x];    }    return ret;}ll get(){    ll ret=0;    for (int i=0;i<n;i++)    {        for (int j=i+1;j<n;j++)            if (ans[i][j]) ret+=(ll)C[i][j];        int x=0;        for (int j=0;j<n;j++)            if (ans[i][j]) x++;        ret+=(ll)H[i][x];    }    return ret;}void trans(){    for (int i=n;i;i--)    {        for (int j=n;j>=0;j--)        {            if (j) c[i][j]=C[i-1][j-1];            h[i][j]=H[i-1][j];        }        c[i][i]=0,h[i][n]=int_inf;    }}int not0(int *a,int n){    int ret=0;    for (int i=1;i<=n;i++)        if (a[i]) ret++;    return ret;}void test1(int &lim){    static int q[M];    int cnt=0;    for (int i=1;i<=n;i++)        if (!d[i])            for (int j=1;j<=n;j++)                if (d[j]&&!vis[i][j])                    q[++cnt]=h[i][D[i]+1]-h[i][D[i]]+c[i][j];    sort(q+1,q+cnt+1);    lim=q[min(cnt,L)];}void work1(int lim){    static edge q[M];    int cnt=0;    for (int i=1;i<=n;i++)        if (!d[i]&&h[i][D[i]+1]-h[i][D[i]]<lim)            for (int j=1;j<=n;j++)                if (d[j]&&!vis[i][j])                    q[++cnt]=(edge){i,j,h[i][D[i]+1]-h[i][D[i]]+c[i][j]};    sort(q+1,q+cnt+1);    for (int i=1;i<=cnt;i++)    {        int x=q[i].x,y=q[i].y;        if (d[y]&&h[x][D[x]+1]-h[x][D[x]]+c[x][y]<=lim)        {            D[x]++,d[y]--;            g[++g_number]=(edge){x,y,c[x][y]};            vis[x][y]=vis[y][x]=1;        }    }}void add_rest(){    static Node q[N];    for (int i=1;i<=n;i++)        while (d[i])        {            int tp=0;            for (int j=1;j<=n;j++)                if (i!=j&&!vis[i][j])                    q[++tp]=(Node){h[j][D[j]+1]-h[j][D[j]]+c[i][j],j};            sort(q+1,q+tp+1);            int j=q[1].y;            g[++g_number]=(edge){i,j,c[i][j]};            vis[i][j]=vis[j][i]=1;            d[i]--,D[j]++;        }}void merge_block(){    static int q[N];    static Node a[N],b[N];    for (int i=1;i<=n;i++) fa[i]=i;    for (int i=1;i<=g_number;i++)    {        int x=g[i].x,y=g[i].y;        fa[find(x)]=find(y);    }    int block_cnt=0,tp=0,na,nb;    for (int i=1;i<=n;i++)        if (find(i)==i) block_cnt++;    while (block_cnt>1)    {        tp=na=nb=0;        for (int i=1;i<=n;i++)            if (find(i)==i) q[++tp]=i;        for (int i=1;i<=n;i++)            if (find(i)==q[1])                a[++na]=(Node){h[i][D[i]+1]-h[i][D[i]],i};            else                if (find(i)==q[2])                    b[++nb]=(Node){h[i][D[i]+1]-h[i][D[i]],i};        sort(a+1,a+na+1),sort(b+1,b+nb+1);        int mn=int_inf,x,y,tx=q[1],ty=q[2];        for (int i=1;i<=na;i++)            for (int j=1;j<=nb;j++)            {                int x=a[i].y,y=b[j].y;                if (!vis[x][y]&&c[x][y]+a[i].x+b[j].x<mn)                {                    mn=c[x][y]+a[i].x+b[j].x;                    tx=x,ty=y;                }            }        g[++g_number]=(edge){tx,ty,c[tx][ty]};        vis[tx][ty]=vis[ty][tx]=1;        D[tx]++,D[ty]++;        fa[find(tx)]=find(ty);        block_cnt--;    }}void get_Ans(){    static int d[N];    int x,y;    memset(d,0,sizeof(d));    for (int i=0;i<n;i++)        for (int j=0;j<n;j++) Ans[i][j]=0;    for (int i=1;i<=g_number;i++)    {        x=g[i].x,y=g[i].y;        d[x]++,d[y]++;        Ans[x-1][y-1]=Ans[y-1][x-1]=1;    }    int tt=3;    while (tt--)    {        for (int i=1;i<n;i++)            for (int j=i+1;j<=n;j++)                if (!vis[i][j])                {                    int tmp=h[i][d[i]+1]-h[i][d[i]];                    tmp+=h[j][d[j]+1]-h[j][d[j]];                    if (tmp+c[i][j]<0)                    {                        vis[i][j]=vis[j][i]=1;                        Ans[i-1][j-1]=Ans[j-1][i-1]=1;                        d[i]++,d[j]++;                    }                }    }}void solve(){    memset(vis,0,sizeof(vis));    int x,y;    for (int i=1;i<=n;i++) vis[i][i]=1;    for (int i=1;i<=n;i++)    {        D[i]=1;        for (int j=2;j<=min(S,ss[i]);j++)            if (h[i][j]<h[i][D[i]]) D[i]=j;    }    g_number=0;    for (int i=1;i<=n;i++) d[i]=D[i];    for (int i=1;i<=number;i++) e[i].x++,e[i].y++;    for (int i=1;i<=number/B;i++)    {        x=e[i].x,y=e[i].y;        if (x==n||y==n) continue;        if (d[x]>0&&d[y]>0)        {            d[x]--,d[y]--;            g[++g_number]=(edge){x,y,e[i].z};            vis[x][y]=vis[y][x]=1;        }    }    for (int i=1;i<=n;i++) ss[i]=D[i]-d[i];    int work1_lim=0;    test1(work1_lim);    for (int i=1;i<100;i++)    {        work1(work1_lim);        if (not0(d,n-1)<3) break;    }    add_rest();    merge_block();    get_Ans();    ll tmp=Get();    if (tmp<Mi_Ans)    {        Mi_Ans=tmp;        Atoa();    }    for (int i=1;i<=number;i++) e[i].x--,e[i].y--;}void change(){    Number=0;    for (int i=0;i<n;i++) First[i]=0;    for (int i=0;i<n;i++)        for (int j=i+1;j<n;j++)            if (Ans[i][j])                E[++Number].add(i,j),E[++Number].add(j,i);    g_number=0;    for (int i=1;i<=number&&g_number<17000;i++)        if (!Ans[e[i].x][e[i].y]) g[++g_number]=e[i];    for (int i=1;i<=g_number;i++)        for (int x=First[g[i].x];x;x=E[x].next)            for (int y=First[g[i].y];y;y=E[y].next)                if (E[x].to!=E[y].to&&Ans[g[i].y][E[y].to]&&Ans[g[i].x][E[x].to])                    if (!Ans[g[i].x][g[i].y]&&!Ans[E[x].to][E[y].to])                        if (C[E[x].to][E[y].to]+g[i].z<C[g[i].x][E[x].to]+C[g[i].y][E[y].to])                        {                            Ans[E[x].to][E[y].to]=Ans[E[y].to][E[x].to]=1;                            Ans[g[i].x][g[i].y]=Ans[g[i].y][g[i].x]=1;                            Ans[g[i].x][E[x].to]=Ans[E[x].to][g[i].x]=0;                            Ans[g[i].y][E[y].to]=Ans[E[y].to][g[i].y]=0;                        }}void init(){    for (int i=1;i<=n;i++) ss[i]=int_inf;    Mi_Ans=ll_inf;    for (int i=0;i<n;i++)        for (int j=0;j<n;j++) ans[i][j]=0;}void WORK0(){    B=1,S=48;    init();    for (int i=1;i<=20;i++) solve();    atoA();    for (int i=1;i<=13;i++) change();}void WORK1(){    B=1,S=35;    init();    for (int i=1;i<=20;i++) solve();    atoA();    for (int i=1;i<=13;i++) change();}void WORK2(){    B=2,S=29,L=30;    init();    for (int i=1;i<=20;i++) solve();    atoA();    for (int i=1;i<=13;i++) change();}void WORK3(){    B=4,S=24,L=30;    init();    for (int i=1;i<=20;i++) solve();    atoA();    for (int i=1;i<=13;i++) change();}void WORK4(){    B=6,S=18,L=30;    init();    for (int i=1;i<=20;i++) solve();    atoA();    for (int i=1;i<=13;i++) change();}void get_d(){    for (int i=0;i<n;i++)    {        d[i]=0;        for (int j=0;j<n;j++)            if (Ans[i][j]) d[i]++;    }}void Delete(){    get_d();    HolmDeLichtenbergThorup HdLT(n+1);    for (int i=0;i<n;i++)        for (int j=i+1;j<n;j++)            if (Ans[i][j]) HdLT.insert(i,j);    g_number=0;    for (int i=0;i<n;i++)        for (int j=i+1;j<n;j++)            if (Ans[i][j]) g[++g_number]=(edge){i,j,C[i][j]};    for (int i=1;i<=g_number;i++)        if (Ans[g[i].x][g[i].y]&&g[i].z+H[g[i].x][d[g[i].x]]+H[g[i].y][d[g[i].y]]>H[g[i].x][d[g[i].x]-1]+H[g[i].y][d[g[i].y]-1])        {            HdLT.erase(g[i].x,g[i].y);            if (!HdLT.is_connected(g[i].x,g[i].y))                HdLT.insert(g[i].x,g[i].y);            else            {                Ans[g[i].x][g[i].y]=Ans[g[i].y][g[i].x]=0;                d[g[i].x]--,d[g[i].y]--;            }        }}void Delete_two(){    get_d();    for (int i=0;i<n;i++) used[i]=0;    g_number=0;    for (int i=0;i<n;i++)        for (int j=i+1;j<n;j++)            if (Ans[i][j]&&!used[i]&&!used[j])                if (C[i][j]+H[i][d[i]]+H[j][d[j]]>H[i][d[i]-1]+H[j][d[j]-1])                {                    Ans[i][j]=Ans[j][i]=0;                    d[i]--,d[j]--;                    used[i]=used[j]=1;                    g[++g_number]=(edge){i,j,C[i][j]};                }    int block_num=0;    for (int i=0;i<n;i++) fa[i]=i;    for (int i=0;i<n;i++)        for (int j=i+1;j<n;j++)            if (Ans[i][j])                if (find(i)!=find(j)) fa[find(i)]=find(j);    for (int i=0;i<n;i++)        if (find(i)==i) block_num++;    sort(g+1,g+g_number+1);    int pos=1;    while (block_num>1)    {        while (find(g[pos].x)==find(g[pos].y)) pos++;        Ans[g[pos].x][g[pos].y]=Ans[g[pos].y][g[pos].x]=1;        fa[find(g[pos].x)]=find(g[pos].y);        block_num--;    }}void add_circle(){    for (int i=0;i<n;i++)        for (int j=i+1;j<n;j++)            if (!Ans[i][j])                for (int k=j+1;k<n;k++)                    if (!Ans[i][j]&&!Ans[i][k]&&!Ans[j][k])                        if (C[i][j]+C[i][k]+C[j][k]+H[i][d[i]+2]+H[j][d[j]+2]+H[k][d[k]+2]<H[i][d[i]]+H[j][d[j]]+H[k][d[k]])                        {                            d[i]+=2,d[j]+=2,d[k]+=2;                            Ans[i][j]=Ans[j][i]=1;                            Ans[i][k]=Ans[k][i]=1;                            Ans[j][k]=Ans[k][j]=1;                        }}void del_circle(){    HolmDeLichtenbergThorup HdLT(n+1);    for (int i=0;i<n;i++)        for (int j=i+1;j<n;j++)            if (Ans[i][j]) HdLT.insert(i,j);    for (int i=0;i<n;i++)        for (int j=i+1;j<n;j++)            if (Ans[i][j])                for (int k=j+1;k<n;k++)                    if (Ans[i][j]&&Ans[i][k]&&Ans[j][k])                        if (C[i][j]+C[i][k]+C[j][k]+H[i][d[i]]+H[j][d[j]]+H[k][d[k]]>H[i][d[i]-2]+H[j][d[j]-2]+H[k][d[k]-2])                        {                            HdLT.erase(i,j);                            HdLT.erase(j,k);                            HdLT.erase(i,k);                            if (HdLT.is_connected(i,j)&&HdLT.is_connected(j,k))                            {                                d[i]-=2,d[j]-=2,d[k]-=2;                                Ans[i][j]=Ans[j][i]=0;                                Ans[i][k]=Ans[k][i]=0;                                Ans[j][k]=Ans[k][j]=0;                            }                            else                            {                                HdLT.insert(i,j);                                HdLT.insert(j,k);                                HdLT.insert(i,k);                            }                        }}void one_to_two(){    g_number=0;    for (int i=0;i<n;i++)        for (int j=i+1;j<n;j++)            if (Ans[i][j]) g[++g_number]=(edge){i,j,C[i][j]};    for (int i=1;i<=g_number;i++)        if (Ans[g[i].x][g[i].y])            for (int j=0;j<n;j++)                if (!Ans[g[i].x][j]&&!Ans[g[i].y][j]&&Ans[g[i].x][g[i].y])                    if (C[j][g[i].x]+C[j][g[i].y]+H[j][d[j]+2]<g[i].z+H[j][d[j]])                    {                        d[j]+=2;                        Ans[g[i].x][g[i].y]=Ans[g[i].y][g[i].x]=0;                        Ans[j][g[i].x]=Ans[g[i].x][j]=1;                        Ans[j][g[i].y]=Ans[g[i].y][j]=1;                        break;                    }}void two_to_one(){    HolmDeLichtenbergThorup HdLT(n+1);    for (int i=0;i<n;i++)        for (int j=i+1;j<n;j++)            if (Ans[i][j]) HdLT.insert(i,j);    g_number=0;    for (int i=0;i<n;i++)        for (int j=i+1;j<n;j++)            if (!Ans[i][j]) g[++g_number]=(edge){i,j,C[i][j]};    sort(g+1,g+g_number+1);    for (int i=1;i<=g_number/5;i++)        if (!Ans[g[i].x][g[i].y])            for (int j=0;j<n;j++)                if (Ans[g[i].x][j]&&Ans[g[i].y][j]&&!Ans[g[i].x][g[i].y])                    if (C[j][g[i].x]+C[j][g[i].y]+H[j][d[j]]>g[i].z+H[j][d[j]-2])                    {                        HdLT.erase(j,g[i].x);                        HdLT.erase(j,g[i].y);                        HdLT.insert(g[i].x,g[i].y);                        if (HdLT.is_connected(g[i].x,j))                        {                            d[j]-=2;                            Ans[g[i].x][g[i].y]=Ans[g[i].y][g[i].x]=1;                            Ans[j][g[i].x]=Ans[g[i].x][j]=0;                            Ans[j][g[i].y]=Ans[g[i].y][j]=0;                            break;                        }                        else                        {                            HdLT.insert(j,g[i].x);                            HdLT.insert(j,g[i].y);                            HdLT.erase(g[i].x,g[i].y);                        }                    }}void circle_change(){    Number=0;    for (int i=0;i<n;i++) First[i]=0;    for (int i=0;i<n;i++)        for (int j=i+1;j<n;j++)            if (Ans[i][j])                E[++Number].add(i,j),E[++Number].add(j,i);    for (int i=0;i<n;i++)        for (int x=First[i];x;x=E[x].next)            for (int y=E[x].next;y;y=E[y].next)                if (Ans[i][E[x].to]&&Ans[i][E[y].to]&&!Ans[E[x].to][E[y].to])                {                    int j=E[x].to,k=E[y].to;                    if (C[i][j]+H[i][d[i]]+H[k][d[k]]>C[j][k]+H[i][d[i]-1]+H[k][d[k]+1])                    {                        d[i]--,d[k]++;                        Ans[i][j]=Ans[j][i]=0;                        Ans[j][k]=Ans[k][j]=1;                        break;                    }                    if (C[i][k]+H[i][d[i]]+H[j][d[j]]>C[j][k]+H[i][d[i]-1]+H[j][d[j]+1])                    {                        d[i]--,d[j]++;                        Ans[i][k]=Ans[k][i]=0;                        Ans[j][k]=Ans[k][j]=1;                        break;                    }                }}bool check(){    for (int i=0;i<n;i++) fa[i]=i;    for (int i=0;i<n;i++) if (Ans[i][i]) return 0;    for (int i=0;i<n;i++)        for (int j=i+1;j<n;j++)            if (Ans[i][j])                if (find(i)!=find(j)) fa[find(i)]=find(j);    int num=0;    for (int i=0;i<n;i++)        if (find(i)==i) num++;    return num==1;}int main(){    if (debug)    {        freopen("1.in","r",stdin);        freopen("1.out","w",stdout);    }    srand(20010527);    int T;    scanf("%d",&T);    Min[0]=43,Max[0]=48;    Min[1]=30,Max[1]=35;    Min[2]=25,Max[2]=29;    Min[3]=17,Max[3]=21;    Min[4]=13,Max[4]=16;    ll ret=0;    for (int tt=0;tt<T;tt++)    {        scanf("%d %d %d",&n,&Cmax,&Hmax);        if (Cmax==40000) id=0;        if (Cmax==100000) id=1;        if (Cmax==200000) id=2;        if (Cmax==500000) id=3;        if (Cmax==1000000) id=4;        number=0;        memset(Ans,0,sizeof(Ans));        for (int i=0;i<n;i++)        {            C[i][i]=0;            scanf("%llu %llu",&s[0],&s[1]);            for (int j=i+1;j<n;j++)            {                C[i][j]=C[j][i]=xorshift128plus()%(Cmax+1);                e[++number]=(edge){i,j,C[i][j]};            }        }        for (int i=0;i<n;i++)        {            scanf("%llu %llu",&s[0],&s[1]);            for (int j=0;j<n;j++)                H[i][j]=xorshift128plus()%(Hmax+1);        }        trans();        sort(e+1,e+number+1);        if (id==0) WORK0();        if (id==1) WORK1();        if (id==2) WORK2();        if (id==3) WORK3();        if (id==4) WORK4();        //Delete();        Delete_two();        get_d();        for (int i=0;i<3;i++) one_to_two();        two_to_one();        //if (id>=4) add_circle();        circle_change();        //del_circle();        assert(check());        print();        ret+=Get();        cerr<<Get()<<endl;    }    cerr<<"The score is: "<<ret<<endl;    return 0;}
原创粉丝点击