読者です 読者をやめる 読者になる 読者になる

PCK追加分

ついに2011本選が追加され始めたので。

0251:
要は各連結成分が直線かどうかを聞いている。

#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
int deg[110000];
int UF[110000];
int FIND(int a){
	if(UF[a]<0)return a;
	return UF[a]=FIND(UF[a]);
}
void UNION(int a,int b){
	a=FIND(a);b=FIND(b);if(a==b)return;
	UF[a]+=UF[b];UF[b]=a;
}
int main(){
	int a,b;
	while(scanf("%d%d",&a,&b),a){
		for(int i=0;i<a;i++)UF[i]=-1;
		for(int i=0;i<a;i++)deg[i]=0;
		for(int i=0;i<b;i++){
			int p,q;
			scanf("%d%d",&p,&q);
			p--;q--;
			UNION(p,q);
			deg[p]++;
			deg[q]++;
		}
		bool ok=true;
		for(int i=0;i<a;i++)if(deg[i]>2)ok=false;
		
		int rk=0;
		for(int i=0;i<a;i++)if(UF[i]<0)rk++;
		if(rk!=a-b)ok=false;
		if(ok)printf("yes\n");
		else printf("no\n");
	}
}

0253:
凸カットを持っていると本当に一瞬。

#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
const double EPS = 1e-10;
const double INF = 1e+10;
const double PI = acos(-1);
//
Pt p[110];
Pt res[210];
int main(){
	int a,b,c;
	while(scanf("%d%d%d",&a,&b,&c),a){
		double S=(double)c/b;
		for(int i=0;i<a;i++){
			double X,Y;
			scanf("%lf%lf",&X,&Y);
			p[i]=Pt(X,Y);
		}
		double ret=0;
		for(int i=0;i<a;i++){
			for(int j=0;j<a;j++){
				if(i!=j)p[j]=p[j]-p[i];
			}
			p[i]=Pt(0,0);
			double th=p[(i+1)%a].arg();
			for(int j=0;j<a;j++){
				p[j]=p[j]*Pt(cos(-th),sin(-th));
			}
			double L=0;
			double R=0;
			for(int j=0;j<a;j++)R=max(R,p[j].y);
			for(int j=0;j<100;j++){
				double M=(L+R)/2;
				int m=convexCut(a,p,Pt(1000,M),Pt(-1000,M),res);
				double tmp=0;
				for(int k=0;k<m;k++)tmp+=res[k].det(res[(k+1)%m]);
				if(tmp<0)tmp=-tmp;
				tmp/=2;
			//	printf("%f: %f\n",M,tmp);
				if(tmp>S)R=M;
				else L=M;
			}
	//		printf("%d: %f\n",i,L);
			ret=max(ret,L);
		}
		printf("%.12f\n",ret);
	}
}

0254:
要は(ある連続する区間の和)%mの最大化。だいぶ記憶が薄れてきていてlog系の良問であったことしか覚えてなかった。

#include<stdio.h>
#include<algorithm>
#include<set>
using namespace std;
long long c[31000];
int d[31000];
int main(){
	int a,b;
	while(scanf("%d%d",&a,&b),a){
		for(int i=0;i<a;i++)scanf("%lld",c+i);
		long long now=0;
		for(int i=0;i<a;i++){
			now+=c[i];
			d[i]=now%b;
		}
		set<int> S;
		S.insert(b);
		int ret=0;
		for(int i=0;i<a;i++){
			int v=*(S.upper_bound(d[i]));
			ret=max(ret,(b+d[i]-v)%b);
			S.insert(d[i]);
		}
		printf("%d\n",ret);
	}
}