151029总结

T1

这道题真是哭笑不得

看到题认为是到Dp,仔细想想好像可以贪心,然后写了个n!的算法验证好像是对的

然后写出贪心和大暴力对拍,没有问题啊,关键是这道题范围n<50,但是贪心是O(n)的

最后还是没有发现错,测了过后也是对的。那么这道题的范围就是出题人用来吓人的啦

ORZgjy看到50想到完全图的最长曼哈顿回路,强行NP一波

给我启示就是不要想太多= = 100

T2

求最大情况的最小值,很明显的二分

二分后的验证?开始想到dp,但是dp是n^3的,或者空间换时间降到n^2 或 n^2log,时间和空间不能平衡

回头想到可以贪心验证啊,贪心每次切最少又满足条件的绝对不会错啊

于是就A了 100

T3

xor题,想了一会大致想出n^2和链的nlogn

然后就写了,还写了第三块卡时随机树的情况

测试时:

啊?我前面不是有两块的部分分吗

回头一看交错文件了

把正确的交上去居然少了10分= =

其实我都把链想出来了,树也就特别简单了

对于链来说,我们可以把xor前缀和扔进一个字典树中

每次加入一个数就查询一个数的二进制反数,一次是log级别的

由于a^b^a=b所以我们可以直接把两个数到根的路径xor起来就是这条xor和路径

然后枚举+查询就可以啦 考场上50(这个运气还不错)


100+100+50,这分数真是暗示了我什么

//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
inline void R(int &v)
{
	v=0;char c=0;int p=1;
	while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
	while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
	v*=p;
}
int a[5001],b[5001],ans;
int main()
{
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
	int T;R(T);
	for(int testcase=1;testcase<=T;testcase++)
	{
		int n;R(n);
		for(int i=1;i<=n;i++)R(a[i]);
		sort(a+1,a+n+1);
		int t=0,ret1=0,ret2=0;
		for(int i=3;i<n;i+=2)b[i]=a[++t];
		b[1]=a[++t],b[n]=a[++t];
		for(int i=2;i<n;i+=2)b[i]=a[++t];
		for(int i=2;i<=n;i++)ret1+=abs(b[i]-b[i-1]);
		t=0;
		for(int i=2;i<n;i+=2)b[i]=a[++t];
		b[1]=a[++t],b[n]=a[++t];
		for(int i=3;i<n;i+=2)b[i]=a[++t];
		for(int i=2;i<=n;i++)ret2+=abs(b[i]-b[i-1]);
		
		printf("Case %d: %d\n",testcase,max(ret1,ret2));
	}
}
//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
inline void R(int &v)
{
	v=0;char c=0;int p=1;
	while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
	while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
	v*=p;
}
int n,m,A,B;
int map[505][505];
int sum[505][505];
int getsum(int x,int y,int i,int j)
{
	return sum[i][j]-sum[x-1][j]-sum[i][y-1]+sum[x-1][y-1];
}
bool check(int num)
{
	int Sum=0;
	for(int i=1;i<=n;i++)
	{
		int stax=i,stay=1;
		int len=0;
		while(1)
		{
			int px=stax,py=stay,tot=0;
			for(int end=1;end<=m;end++)
			{
				if(getsum(px,py,px+len,end)>=num)
				{
					tot++;
					py=end+1;
				}
			}
			if(tot>=B)break;
			len++;
			if(stax+len>n)return Sum>=A;
		}
		i+=len;Sum++;
	}
	return Sum>=A;
} 
int main()
{
	freopen("cut.in","r",stdin);
	freopen("cut.out","w",stdout);
	R(n),R(m),R(A),R(B);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			R(map[i][j]);
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+map[i][j];
		}
	}
	//cerr<<getsum(1,1,1,1)<<endl;
	//cerr<<check(4);
	int l=1,r=1000000001;
	while(l<r)
	{
		int mid=l+r>>1;
		if(check(mid))l=mid+1;
		else r=mid;
	}
	printf("%d\n",l-1);
}

//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
inline void R(int &v)
{
	v=0;char c=0;int p=1;
	while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
	while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
	v*=p;
}
struct Edge
{
	int to,next,len;
}edge[200001];
int size,first[100010];
int val[100010];
bool vis[100010];
int w[3100010][2],tot;
int ans;
int n;
void addedge(int x,int y,int z)
{
	size++;
	edge[size].to=y;
	edge[size].next=first[x];
	first[x]=size;
	edge[size].len=z;
}
void dfs(int now)
{
	vis[now]=true;
	for(int u=first[now];u;u=edge[u].next)
	{
		if(!vis[edge[u].to])
		{
			val[edge[u].to]=val[now]^edge[u].len;
			dfs(edge[u].to);
		}
	}
}
int main()
{
	int _q=40<<20;
	char *_p=(char*)malloc(_q)+_q;
	__asm__("movl %0, %%esp\n"::"r"(_p));
	freopen("xor.in","r",stdin);
	freopen("xor.out","w",stdout);
	R(n);
	for(int i=1;i<=n-1;i++)
	{
		int x,y,z;
		R(x),R(y),R(z);
		addedge(x,y,z);
		addedge(y,x,z);
	}
	dfs(1);
	for(int i=1;i<=n;i++)
	{
		int k=val[i];
		static int p[32];
		for(int i=31;i>=1;i--)
		{
			p[i]=(k&1);
			k>>=1;
		}
		int now=0;
		for(int i=1;i<=31;i++)
		{
			if(!w[now][p[i]])w[now][p[i]]=++tot;
			now=w[now][p[i]];
		}
		now=0;int ret=0;
		for(int i=1;i<=31;i++)
		{
			if(w[now][!p[i]])now=w[now][!p[i]],ret+=(1<<(31-i));
			else now=w[now][p[i]];
		}
		ans=max(ans,ret);
	}
	cout<<ans<<endl;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值