Codeforces Round #532 (Div. 2)

终于。。

A - Roman and Browser

有很多写法,当然我也知道可以暴力,但是前缀和的写法就很舒服啊。

#include<bits/stdc++.h>
using namespace std;

char gc() {
//	static char buf[100000],*p1,*p2;
//	return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin))?EOF:*p1++;
	return getchar();
}

template<class T>
int read(T &ans) {
	T f=1;ans=0;
	char ch=gc();
	while(!isdigit(ch)) {
		if(ch==EOF) return EOF;
		if(ch=='-') f=-1;
		ch=gc();
	}
	while(isdigit(ch))
		ans=ans*10+ch-'0',ch=gc();
	ans*=f;return 1;
}

template<class T1,class T2>
int read(T1 &a,T2 &b) {
	return read(a)==EOF?EOF:read(b);
}

template<class T1,class T2,class T3>
int read(T1 &a,T2 &b,T3 &c) {
	return read(a,b)==EOF?EOF:read(c);
}

typedef long long ll;
const int Maxn=1100000;
const int inf=0x3f3f3f3f;
const ll mod=998244353;

int n,k,a[Maxn],s[Maxn],sum,ans;

int main() {
	read(n,k);
	for(int i=1;i<=n;i++)
		read(a[i]),sum+=a[i];
	for(int i=1;i<k;i++) s[i]=a[i];
	for(int i=k;i<=n;i++) s[i]=s[i-k]+a[i];
	for(int i=n-k+1;i<=n;i++) ans=max(ans,abs(sum-s[i]));
	printf("%d",ans);
	return 0;
}

B - Build a Contest

根据题意直接模拟即可。

#include<bits/stdc++.h>
using namespace std;

char gc() {
//	static char buf[100000],*p1,*p2;
//	return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin))?EOF:*p1++;
	return getchar();
}

template<class T>
int read(T &ans) {
	T f=1;ans=0;
	char ch=gc();
	while(!isdigit(ch)) {
		if(ch==EOF) return EOF;
		if(ch=='-') f=-1;
		ch=gc();
	}
	while(isdigit(ch))
		ans=ans*10+ch-'0',ch=gc();
	ans*=f;return 1;
}

template<class T1,class T2>
int read(T1 &a,T2 &b) {
	return read(a)==EOF?EOF:read(b);
}

template<class T1,class T2,class T3>
int read(T1 &a,T2 &b,T3 &c) {
	return read(a,b)==EOF?EOF:read(c);
}

typedef long long ll;
const int Maxn=1100000;
const int inf=0x3f3f3f3f;
const ll mod=998244353;

int n,m,x,cnt[Maxn];

int main() {
	read(n,m);
	int temp=0;
	for(int i=1;i<=m;i++) {
		read(x);
		if(cnt[x]==0)
			temp++;
		cnt[x]++;
		if(temp==n) {
			putchar('1');
			for(int i=1;i<=n;i++) {
				cnt[i]--;
				if(cnt[i]==0) temp--;
			}
		}
		else putchar('0');
	}
	putchar('\n');
	return 0;
}

C - NN and the Optical Illusion

如上图,长度为2r的边就是正n边形的边,那么\(\theta = \frac{2\pi}{n}\)

那么由余弦定理知,\(c^2=a^2+b^2-2ab\cos C\),那么这里的\(a=b=R+r,c=2r,C=\theta\),化一下式子就出来了。

#include<bits/stdc++.h>
using namespace std;

char gc() {
//	static char buf[100000],*p1,*p2;
//	return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin))?EOF:*p1++;
	return getchar();
}

template<class T>
int read(T &ans) {
	T f=1;ans=0;
	char ch=gc();
	while(!isdigit(ch)) {
		if(ch==EOF) return EOF;
		if(ch=='-') f=-1;
		ch=gc();
	}
	while(isdigit(ch))
		ans=ans*10+ch-'0',ch=gc();
	ans*=f;return 1;
}

template<class T1,class T2>
int read(T1 &a,T2 &b) {
	return read(a)==EOF?EOF:read(b);
}

template<class T1,class T2,class T3>
int read(T1 &a,T2 &b,T3 &c) {
	return read(a,b)==EOF?EOF:read(c);
}

typedef long long ll;
const int Maxn=1100000;
const int inf=0x3f3f3f3f;
const ll mod=998244353;
const double Pi=acos(-1);

int n,R;

int main() {
	read(n,R);
	double d=2.0*cos(2.0*Pi/n);
	double a=2.0+d,b=(4.0-2.0*d)*R,c=(2.0-d)*R*R;
	printf("%.11lf",(b+sqrt(b*b+4.0*a*c))/(2.0*a));
	return 0;
}

D - Dasha and Chess

首先把king移动到中间,然后看一下现在以king为中心的四个象限中那个里面的车最少,然后往相反的方向移。因为少的那个不会超过四分之一也就是166,那另外的三个象限纵沟至少是500个,而king移动的时候另一个人必须把这500个全部放到相反的那个象限里面,而king只会走499步,那么一定能赢。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cctype>
#define qmin(x,y) (x=min(x,y))
#define qmax(x,y) (x=max(x,y))
using namespace std;

inline char gc() {
//	static char buf[100000],*p1,*p2;
//	return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
	return getchar();
}

template<class T>
int read(T &ans) {
	ans=0;char ch=gc();T f=1;
	while(!isdigit(ch)) {
		if(ch==EOF) return -1;
		if(ch=='-') f=-1;
		ch=gc();
	}
	while(isdigit(ch))
		ans=ans*10+ch-'0',ch=gc();
	ans*=f;return 1;
}

template<class T1,class T2>
int read(T1 &a,T2 &b) {
	return read(a)!=EOF&&read(b)!=EOF?2:EOF;
}

template<class T1,class T2,class T3>
int read(T1 &a,T2 &b,T3 &c) {
	return read(a,b)!=EOF&&read(c)!=EOF?3:EOF;
}

typedef long long ll;
const int Maxn=1100;
const int inf=0x3f3f3f3f;
const int c=500;

int nx,ny,a[Maxn][Maxn],x[Maxn],y[Maxn];

void get(int X,int Y) {
	if(nx>X) nx--;
	else if(nx<X) nx++;
	if(ny>Y&&!a[nx][ny-1]) ny--;
	else if(ny<Y&&!a[nx][ny+1]) ny++;
}

void work(int X,int Y) {
	while(nx!=X||ny!=Y) {
		get(X,Y);
		printf("%d %d\n",nx,ny);
		fflush(stdout);
		int b;
		read(b);
		if(b<=-1) exit(0);
		a[x[b]][y[b]]=0;
		read(x[b],y[b]);
		a[x[b]][y[b]]=1;
	}
}

signed main() {
//	freopen("test.in","r",stdin);
	read(nx,ny);
	for(int i=1;i<=666;i++) read(x[i],y[i]),a[x[i]][y[i]]=1;
	work(c,c);
	int zhy=0;
	for(int i=1;i<=c;i++) for(int j=1;j<=c;j++) if(a[i][j]) zhy++;
	if(zhy<=166) work(999,999);zhy=0;
	for(int i=1;i<=c;i++) for(int j=c;j<=999;j++) if(a[i][j]) zhy++;
	if(zhy<=166) work(999,1);zhy=0;
	for(int i=c;i<=999;i++) for(int j=1;j<=c;j++) if(a[i][j]) zhy++;
	if(zhy<=166) work(1,999);
	work(1,1);
	return 0;
}


E - Andrew and Taxi

首先把边按权值从小到大排序,然后二分最后的发生变向的边是哪一个。

那么这条边后面的边一定都没有变向,如果这里面有环,那么就排除,然后继续二分。

最后求出来为使得后面没有环,最后的发生变向的边。显然后面的边形成一个DAG,那么求出来DAG上的拓扑序,然后对于所有的边,由拓扑序小的指向拓扑序大的即可。

#include<bits/stdc++.h>
using namespace std;

char gc() {
//	static char buf[100000],*p1,*p2;
//	return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin))?EOF:*p1++;
	return getchar();
}

template<class T>
int read(T &ans) {
	T f=1;ans=0;
	char ch=gc();
	while(!isdigit(ch)) {
		if(ch==EOF) return EOF;
		if(ch=='-') f=-1;
		ch=gc();
	}
	while(isdigit(ch))
		ans=ans*10+ch-'0',ch=gc();
	ans*=f;return 1;
}

template<class T1,class T2>
int read(T1 &a,T2 &b) {
	return read(a)==EOF?EOF:read(b);
}

template<class T1,class T2,class T3>
int read(T1 &a,T2 &b,T3 &c) {
	return read(a,b)==EOF?EOF:read(c);
}

typedef long long ll;
const int Maxn=1100000;
const int inf=0x3f3f3f3f;
const ll mod=998244353;
const double Pi=acos(-1);

int n,m,d[Maxn],first[Maxn],nxt[Maxn],to[Maxn],tot=1,vis[Maxn],bj[Maxn];
queue<int> q;

inline void add(int u,int v) {
	to[tot]=v;
	nxt[tot]=first[u];
	first[u]=tot++;
}

int dfs(int root) {
	vis[root]=1;
	bj[root]=1;
	for(int i=first[root];i;i=nxt[i])
		if(bj[to[i]]) {
			bj[root]=0;
			return 1;
		}
		else if(dfs(to[i])) {
			bj[root]=0;
			return 1;
		}
	bj[root]=0;
	return 0;
}

struct node {
	int u,v,w,id;
}a[Maxn];

int cmp(node a,node b) {
	return a.w<b.w;
}

int main() {
	read(n,m);
	for(int i=1;i<=m;i++) {
		read(a[i].u,a[i].v,a[i].w);
		a[i].id=i;
	}
	sort(a+1,a+m+1,cmp);
	int l=1,r=m,mid=l+r>>1,ans=0;
	while(l<=r) {
		memset(first,0,sizeof(first));
		memset(vis,0,sizeof(vis));
		tot=1;int flag=0;
		for(int i=mid;i<=m;i++) add(a[i].u,a[i].v);
		for(int i=1;i<=n;i++) if(!vis[i]) {
			if(dfs(i)) {
				flag=1;
				break;
			}
		}
		if(flag)
			l=mid+1;
		else {
			r=mid-1;
			ans=mid;
		}
		mid=l+r>>1;
	}
	memset(first,0,sizeof(first));tot=1;
	for(int i=ans;i<=m;i++)
		add(a[i].u,a[i].v),d[a[i].v]++;
	for(int i=1;i<=n;i++) if(!d[i]) q.push(i);
	int cnt=0;
	while(!q.empty()) {
		int now=q.front();q.pop();
		vis[now]=++cnt;
		for(int i=first[now];i;i=nxt[i]) {
			d[to[i]]--;
			if(!d[to[i]]) q.push(to[i]);
		}
	}
	cnt=0;
	for(int i=1;i<=m;i++)
		if(vis[a[i].v]<vis[a[i].u]) d[a[i].id]=1,cnt++;
	if(!ans) ans++;
	printf("%d %d\n",a[ans-1].w,cnt);
	for(int i=1;i<=m;i++) if(d[i]) printf("%d ",i);
	return 0;
}

F - Ivan and Burgers

开始的时候想用ST表套线性基,卡了一会空间之后才发现空间复杂度是假的,于是膜拜了一下别人的神奇写法。

就是把右端点相同的询问放在一起处理,由于有了位置这个限制,那么我们贪心地一定是优先选靠右的点,未来的用处一定更大,如果你会线性基的话,看一下代码就明白了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cctype>
#define qmin(x,y) (x=min(x,y))
#define qmax(x,y) (x=max(x,y))
using namespace std;

inline char gc() {
//	static char buf[100000],*p1,*p2;
//	return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
	return getchar();
}

template<class T>
int read(T &ans) {
	ans=0;char ch=gc();T f=1;
	while(!isdigit(ch)) {
		if(ch==EOF) return -1;
		if(ch=='-') f=-1;
		ch=gc();
	}
	while(isdigit(ch))
		ans=ans*10+ch-'0',ch=gc();
	ans*=f;return 1;
}

template<class T1,class T2>
int read(T1 &a,T2 &b) {
	return read(a)!=EOF&&read(b)!=EOF?2:EOF;
}

template<class T1,class T2,class T3>
int read(T1 &a,T2 &b,T3 &c) {
	return read(a,b)!=EOF&&read(c)!=EOF?3:EOF;
}

typedef long long ll;
const int Maxn=500001;
const int inf=0x3f3f3f3f;

int n,a[Maxn],q,l[Maxn],x,ans[Maxn],p[21],po[21];
vector<int> v[Maxn];

signed main() {
//	freopen("test.in","r",stdin);
	read(n);
	for(int i=1;i<=n;i++) read(a[i]);
	read(q);
	for(int i=1;i<=q;i++) {
		read(l[i],x);
		v[x].push_back(i);
	}
	for(int i=1;i<=n;i++) {
		int x=a[i],y=i;
		for(int j=20;j>=0;j--) if(x&(1<<j)) {
			if(!p[j]) { p[j]=x; po[j]=y; break; }
			if(po[j]<y) swap(x,p[j]),swap(y,po[j]);
			x^=p[j];
		}
		for(int j=0;j<v[i].size();j++)
			for(int k=20;k>=0;k--) if(po[k]>=l[v[i][j]])
				qmax(ans[v[i][j]],ans[v[i][j]]^p[k]);
	}
	for(int i=1;i<=q;i++) printf("%d\n",ans[i]);
	return 0;
}


posted @ 2019-01-14 09:11  shanxizeng  阅读(232)  评论(0编辑  收藏  举报
广告位招商,有意者请联系