ARC 103简要题解

C /\/\/\/

奇偶分类然后就是送分题,代码懒得写了。

D Robot Arms

非常强的二进制拆分,见代码。(题解自己看去

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
vector<int> v;
void sol(int x,int y)
{
	for(int i=0;i<v.size();i++)
	{
		int s=v[i];
		if(abs(x)>abs(y))
		{
			if(x<0)x+=s,putchar('L');
			else x-=s,putchar('R');
		}
		else
		{
			if(y<0)y+=s,putchar('D');
			else y-=s,putchar('U');
		}
	}
	putchar('\n');
}
const int N=1010;
int x[N],y[N],c[2];
int main()
{
	int n=read();
	for(int i=1;i<=n;i++)x[i]=read(),y[i]=read(),c[x[i]+y[i]&1]++;
	if(c[0]&&c[1])return puts("-1"),0;
	for(int i=30;i>=0;i--)v.push_back(1<<i);
	if(c[0])v.push_back(1);
	printf("%d\n",(int)v.size());
	for(int i=0;i<v.size();i++)printf("%d ",v[i]);putchar('\n');
	for(int i=1;i<=n;i++)sol(x[i],y[i]);
	return 0;
}

E Tr/ee

感觉这个 E 比 D 简单,因为我都能想出来。。。

有解当且仅当:

  1. \(\forall 1\le i<n,s_i=s_{n-i}\)
  2. \(s_1=s_{n-1}=1\)
  3. \(s_n=0\)

\(s_i=1\) 的下标拎到一个 \(p_1,p_2,\cdots,p_m\) 里,那么弄一个长度为 \(m\) 的链,并且第 \(i\)\(2<i\le m\))个点挂上 \(p_i-p_{i-1}-1\) 个点。这样是 \(n-1\) 个点,往第 \(m\) 个点再挂一个即可。

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
const int N=1e5+10;
char s[N];int p[N],c; 
int main()
{
	scanf("%s",s+1);
	int n=strlen(s+1);
	if(s[1]=='0'||s[n-1]=='0'||s[n]=='1')return puts("-1"),0;
	for(int i=1;i<n;i++)if(s[i]!=s[n-i])return puts("-1"),0;
	for(int i=1;i<=n;i++)if(s[i]^48)p[++c]=i;
	int m=c;
	for(int i=2;i<=c;i++)
	{
		printf("%d %d\n",i,i-1);
		for(int j=1;j<=p[i]-p[i-1]-1;j++)printf("%d %d\n",i,++m);
	}
	printf("%d %d\n",c,++m);
	return 0;
}

F Distance Sums

考虑以重心为根,那么重心的 \(D_i\) 一定是最大的,最大的 \(D_i\) 一定是叶子,且在这个有根树内一对相邻的点 \((u,v)\)\(u=\mathrm{father}(v)\))满足 \(D_u=2sz_v+D_v-n\)(换根即可得到)。那么每次在 \(D\) 里面二分找 \(D_u\) 的父节点即可。

最后还需要 check 一下,因为只满足了 \(\Delta D\),不一定满足所有 \(D\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define int long long
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}

const int N=1e5+10,M=2e5+10;
int head[N],ver[M],nxt[M],tot=0,n;
void add(int x,int y)
{
	ver[++tot]=y;
	nxt[tot]=head[x];
	head[x]=tot;
}
int f[N];int sz[N];
void dfs(int x,int fa)
{
	for(int i=head[x];i;i=nxt[i])
	{
		int y=ver[i];if(y==fa)continue;
		dfs(y,x);
		f[x]+=f[y];
	}
	f[x]+=sz[x]-1;
//	printf("f[%d]+=%d\n",x,sz[x]-1);
}
int g[N];
void dfs1(int x,int fa)
{
	for(int i=head[x];i;i=nxt[i])
	{
		int y=ver[i];if(y==fa)continue;
		g[y]=g[x]-2*sz[y]+n;
		dfs1(y,x);
	}
}
struct node
{
	int pos,val;
	bool operator<(const node &x)const {return val>x.val;}
}a[N];
signed main()
{
	n=read();
	for(int i=1;i<=n;i++)a[i].val=read(),a[i].pos=i;
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++)sz[i]=1;
	vector<pair<int,int> > ans;
	for(int i=1;i<n;i++)
	{
		int l=i+1,r=n,pos=0;
		while(l<=r)
		{
			int mid=(l+r)/2;
			if(a[mid].val>=a[i].val+2*sz[i]-n)pos=mid,l=mid+1;
			else r=mid-1;
		}
		if(!pos)return puts("-1"),0;
		if(a[pos].val!=a[i].val+2*sz[i]-n)return puts("-1"),0;
		ans.push_back(make_pair(a[i].pos,a[pos].pos));
		add(i,pos),add(pos,i);
		sz[pos]+=sz[i];
	}
	dfs(n,0),g[n]=f[n],dfs1(n,0);
	for(int i=1;i<=n;i++)if(a[i].val!=g[i])return puts("-1"),0;
	for(int i=0;i<n-1;i++)printf("%lld %lld\n",ans[i].first,ans[i].second);
	return 0;
}
posted @ 2021-06-26 16:19  zzt1208  阅读(70)  评论(1编辑  收藏  举报