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
然后就统计出正负两个最大的那个各转移一下就好啦。
#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:在这个区间左边放一个高度
#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
这道题先算出答案为某个值
#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分啊。。果然技不如人。。
题意就是给一张无向图,告诉你连边
考虑给每个点一个度数(度数代价最小的度数),然后尽量去满足,边从小到大加入,这样的话,最后可能不连通,然后就用用最小的代价合并连通块。然后主要就是调试参数(度数上限,加边上限)和加优化(三个点换边,四个点换边等等)。
似乎这样就有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;}
阅读全文
0 0
- codechef October Challenge 2017解题报告
- [Contest]CodeChef October Challenge 2017
- codechef September Challenge 2017解题报告
- codechef November Challenge 2017解题报告
- [多维FFT Bluestein′s Algorithm] Codechef October Challenge 2017 .Chef and Horcrux
- [最小生成树 并查集] Codechef October Challenge 2017 .Lucky Edge
- Codechef April Challenge 2017
- [CodeChef FEB14]Graph Challenge解题报告(求半支配点)
- CodeChef SnakeDown2017 E解题报告
- CodeChef March Challenge 2017 题解
- BSOJ4835刷漆(Codechef October Challenge 2014:Remy paints the fence)
- [CodeChef FEB15]Payton numbers(CUSTPRIM)解题报告
- Codechef 2017 March Challenge 简要题解
- 在流程图中求支配点的一种快速算法+[CodeChef FEB14]Graph Challenge解题报告(求半支配点)
- 【解题报告】Intel Code Challenge Elimination Round
- Cdqz_Openjudge1010 Challenge 10 解题报告【数据结构】【分块】
- codechef December Challenge 2012
- codechef December Challenge 2012
- qt在opencv下编译成功,运行不成功的问题解决
- 数组
- 开博语
- StringRedisTemplate常用操作 / Redis中删除过期Key的三种策略
- jenkins+maven+svn实现简单的一键发布
- codechef October Challenge 2017解题报告
- unity vrtk知识点
- 000
- Qt 按钮被遮挡,点击响应
- css行高line-height的用法
- zjoi2007棋盘分割
- 基础篇
- Android 关闭一个线程
- 优秀工程师-IOS开发中的CGFloat、CGPoint、CGSize和CGRect