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;
}