第二次打challenge。。果然还是拿不到钱(艹不过大佬)啊。
A Balanced Contest
模拟就好。
#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
using 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 1000009
using 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 4294967296ll
using 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 100009
using 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 200009
using 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
然后就统计出正负两个最大的那个各转移一下就好啦。
#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
#define N 1000009
#define inf (ll)1e18
using 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,r
using 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 10009
using 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
这道题先算出答案为某个值
#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
#define N 1000009
#define mod 330301441
#define M 11
using 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分啊。。果然技不如人。。
题意就是给一张无向图,告诉你连边
考虑给每个点一个度数(度数代价最小的度数),然后尽量去满足,边从小到大加入,这样的话,最后可能不连通,然后就用用最小的代价合并连通块。然后主要就是调试参数(度数上限,加边上限)和加优化(三个点换边,四个点换边等等)。
似乎这样就有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 1
using 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;
}