Codeforce Educational Round 6

Codeforce Educational Round 6

A:答案就是max(abs(x1-x2),abs(y1-y2)).

B:打一张表就行了。

C:题意:将一个序列尽量分成多的线段,线段两两不相交且每一条线段中都有且仅有一对权值相同的数。

贪心即可,用map代替hash,每次找到2个就clear。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
map mp;
void build(int Now,int l,int r) {
	if(l == r) return ;
	int Mid = (l + r) >> 1;
	build(Now << 1,l,Mid);
	build(Now << 1 | 1,Mid + 1,r);
}
int n,a,x[300010],y[300010],Ans = 0;
int main() {
	build(1,1,1000);
	scanf("%d",&n);
	int head = 1;
	for(int i = 1;i <= n;i ++)
	{
		scanf("%d",&a);
		mp[a] ++ ;
		if(mp[a] >= 2) Ans ++,x[Ans] = head,y[Ans] = i,mp.clear(),head = i + 1;
	}
	if(Ans == 0) printf("-1");
	else 
	{
		cout<


D:题意:给出两个序列,可以交换0-2个数使得两序列所有数之和的差的绝对值最小。

(序列长度小于等于2000)

交换0次就是原本的和之差。(o(n+m))

交换一次可以n*m枚举。(o(n*m))

我们这样考虑,设第一个序列选了和为x的两个数,第二个序列选了和为y的两个数,那么最终答案就是abs(s1- s2-2*x+2*y),为了使答案最小,2*y-2*x就要尽量接近s2-s2,所以当选了一个x之后,选使得s1-s2+2*y最接近2*x的两个数比较优,我们注意到这是有单调性的。那么我们n^2+m^2求出所有的组合,分别排序,拿一个队列单调扫一下就行了。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define Int long long
using namespace std;
struct node{Int val;int x;int y;
};node f[5000010],g[5000010];
Int A[2010],B[2010],Ans,s1 = 0,s2 = 0;
int x1,x2,x3,x4,n,m,tot,cnt;
bool comp(const node &x,const node &y) {return x.val < y.val;}
bool comp2(const node &x,const node &y) {return x.val == y.val;}
void work1() {
	for(int i = 1;i <= n;i ++)
	    for(int j = 1;j <= m;j ++)
	    {
	    	Int x = abs(s1 - s2 - 2ll * A[i] + 2ll * B[j]);
	    	if(x < Ans)
	    	{
	    		Ans = x;
	    		x1 = i;
	    		x2 = j;
	    	}
	    }
}
void work2() {
	if(n < 2 || m < 2) return ;
	for(int i = 1;i <= n;i ++)
	    for(int j = i + 1;j <= n;j ++)
	    {
	    	f[ ++ tot].val = A[i] + A[j];
	    	f[tot].x = i;
	    	f[tot].y = j;
	    }
	for(int i = 1;i <= m;i ++)
	    for(int j = i + 1;j <= m;j ++)
	    {
	    	g[ ++ cnt].val = B[i] + B[j];
	    	g[cnt].x = i;
	    	g[cnt].y = j;
	    }
	sort(f + 1,f + tot + 1,comp);
	tot = unique(f + 1,f + tot + 1,comp2) - f - 1;
	sort(g + 1,g + cnt + 1,comp);
	cnt = unique(g + 1,g + cnt + 1,comp2) - g - 1;
	int head = 1;
	for(int i = 1;i <= tot;i ++)
	{
		Int x = (s1 - s2 + 2ll * g[head].val);
		Int y = (s1 - s2 + 2ll * g[head + 1].val);
		while(head < cnt && abs(y - 2ll * f[i].val) < abs(x - 2ll * f[i].val))
		{
			head ++;
			x = (s1 - s2 + 2ll * g[head].val);
			y = (s1 - s2 + 2ll * g[head + 1].val);
		}
		Int ret = abs(s1 - s2 - 2ll * f[i].val + 2ll * g[head].val);
		if(ret < Ans)
		{
			Ans = ret;
			x1 = f[i].x;
			x3 = f[i].y;
			x2 = g[head].x;
			x4 = g[head].y;
		}
	}
}
int main() {
	scanf("%d",&n);
	for(int i = 1;i <= n;i ++)
	    cin>>A[i],s1 += A[i];
	scanf("%d",&m);
	for(int i = 1;i <= m;i ++)
	    cin>>B[i],s2 += B[i];
	Ans = abs(s1 - s2);
	work1();
	work2();
	if(x3 != 0) cout<


E:题意:一棵树,点上有颜色,每次覆盖子树颜色,或者询问子树颜色种数。(颜色种数小于60种。)

Claris大大说可以无视颜色搞好害怕….

我们想到60种颜色正好在longlong 范围内,所以我们在线段树中维护二进制数,每次更新用 | 运算维护就可以了。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define Int long long
using namespace std;
struct node{int to;int next;
};node bian[800010];
int in[400010],out[400010],first[400010],size = 0;
int F[1600010],tim = 0,c[400010],n,m,a,b,p,Ans,num[400010];
Int val[1600010];
void inser(int x,int y) {
	size ++;
	bian[size].to = y;
	bian[size].next = first[x];
	first[x] = size;
}
void dfs(int x,int Anc) {
	in[x] = out[x] = ++ tim;num[tim] = x;
	for(int u = first[x];u;u = bian[u].next)
	    if(bian[u].to != Anc)
	    {
	    	dfs(bian[u].to,x);
	    	out[x] = max(out[x],out[bian[u].to]);
	    }
}
void pushdown(int Now) {
	F[Now << 1] = F[Now << 1 | 1] = F[Now];
	val[Now << 1] = val[Now << 1 | 1] = (1ll << (F[Now] - 1));
	F[Now] = 0;
	return ;
}
void build(int Now,int l,int r) {
	if(l == r)
	{
		val[Now] = (1ll << (c[num[l]] - 1));
		return ;
	}
	int Mid = (l + r) >> 1;
	build(Now << 1,l,Mid);
	build(Now << 1 | 1,Mid + 1,r);
	val[Now] = val[Now << 1] | val[Now << 1 | 1];
}
void modify(int Now,int l,int r,int x,int y,int z) {
	if(l >= x && r <= y)
	{
		F[Now] = z;
		val[Now] = (1ll << (z - 1));
		return ;
	}
	if(F[Now] != 0) pushdown(Now);
	int Mid = (l + r) >> 1;
	if(x <= Mid) modify(Now << 1,l,Mid,x,y,z);
	if(y > Mid) modify(Now << 1 | 1,Mid + 1,r,x,y,z);
	val[Now] = val[Now << 1] | val[Now << 1 | 1];
}
Int Ask(int Now,int l,int r,int x,int y) {
	if(l >= x && r <= y) return val[Now];
	if(F[Now] != 0) pushdown(Now);
	int Mid = (l + r) >> 1;
	Int ret = 0;
	if(x <= Mid) ret |= Ask(Now << 1,l,Mid,x,y);
	if(y > Mid) ret |= Ask(Now << 1 | 1,Mid + 1,r,x,y);
	val[Now] = val[Now << 1] | val[Now << 1 | 1];
	return ret;
}
int main() {
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= n;i ++) scanf("%d",&c[i]);
	for(int i = 1;i < n;i ++)
	{
		scanf("%d%d",&a,&b);
		inser(a,b);
		inser(b,a);
	}
	dfs(1,1);
	build(1,1,n);
	for(int i = 1;i <= m;i ++)
	{
		scanf("%d",&p);
		if(p == 1)
		{
			scanf("%d%d",&a,&b);
			modify(1,1,n,in[a],out[a],b);
		}
		else 
		{
			Ans = 0;
			scanf("%d",&a);
			Int w = Ask(1,1,n,in[a],out[a]);
			while(w > 0)
			{
				if(w % 2 == 1) Ans ++;
			    w >>= 1;
			}
			printf("%d\n",Ans);
		}
	}
	return 0;
}


你可能感兴趣的:(Codeforces)