雅礼集训2019 Day4

成功获得成就:和出题人的std错法一样

大爷

codeforces1061E
根据子树之间的限制关系建边跑最大费用流即可。
没错就是这道题我跟标程错的一毛一样。
真·代码:

#include
#define ri register int
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
const int N=2005,M=6e5+5,inf=0x3f3f3f3f;
int n,m,X,Y,s,t,cnt=-1,tot=0,first[N],dis[N],pred[N],pos[N],ans=0,w[N],lim[N],siz[N],A,B;
bool in[N];
vector<int>g[N][2],son[N];
struct edge{int v,c,next,w;}e[M<<1];
inline void add(int u,int v,int c,int w){
	e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt,e[cnt].w=w,e[cnt].c=c;
	e[++cnt].v=u,e[cnt].next=first[v],first[v]=cnt,e[cnt].w=-w,e[cnt].c=0;
}
inline bool spfa(){
	queue<int>q;
	for(ri i=s;i<=t;++i)pred[i]=-1,in[i]=0,dis[i]=-inf,pos[i]=-1;
	dis[s]=0,in[s]=1,q.push(s);
	while(!q.empty()){
		int x=q.front();
		q.pop(),in[x]=0;
		for(ri i=first[x];~i;i=e[i].next){
			int v=e[i].v;
			if(e[i].c&&dis[v]<dis[x]+e[i].w){
				dis[v]=dis[x]+e[i].w,pred[v]=x,pos[v]=i;
				if(!in[v])in[v]=1,q.push(v);
			}
		}
	}
	if(dis[t]==-inf)return 0;
	ans+=dis[t];
	int p=t;
	while(p^s)--e[pos[p]].c,++e[pos[p]^1].c,p=pred[p];
	return 1;
}
void dfs(int p,int fa,int op){
	son[p].push_back(p);
	int tmp=0;
	for(ri i=0,v;i<g[p][op].size();++i){
		if((v=g[p][op][i])==fa)continue;
		dfs(v,p,op),tmp+=siz[v];
		for(ri j=0;j<son[v].size();++j)son[p].push_back(son[v][j]);
	}
	if(~lim[p]){
		if(tmp>lim[p])puts("-1"),exit(0);
		if(lim[p]>tmp){
			int idx=++tot;
			if(!op)add(s,idx,lim[p]-tmp,0);
			else add(idx,t,lim[p]-tmp,0);
			for(ri i=0;i<son[p].size();++i){
				if(!op)add(idx,son[p][i],1,0);
				else add(son[p][i]+n,idx,1,0);
			}
		}
		son[p].clear();
	}
	siz[p]=~lim[p]?lim[p]:tmp;
}
inline void solve(int op){
	for(ri i=1;i<=n;++i)son[i].clear(),lim[i]=-1,siz[i]=0;
	int q=read();
	for(ri i=1,x,v;i<=q;++i){
		x=read(),v=read(),lim[x]=v;
		if(x==X&&!op)A=v;
		if(x==Y&&op)B=v;
	}
	dfs(op?Y:X,0,op);
}
int main(){
	memset(first,-1,sizeof(first));
	n=read(),s=0,tot=n*2,t=n*4+1,X=read(),Y=read();
	for(ri i=1;i<=n;++i)w[i]=read(),add(i,i+n,1,w[i]);
	for(ri i=1,u,v;i<n;++i)u=read(),v=read(),g[u][0].push_back(v),g[v][0].push_back(u);
	for(ri i=1,u,v;i<n;++i)u=read(),v=read(),g[u][1].push_back(v),g[v][1].push_back(u);
	solve(0),solve(1);
	if(A^B)return puts("-1"),0;
	while(spfa());
	bool f=1;
	for(ri i=first[s];~i;i=e[i].next)if(e[i].c)f=0;
	for(ri i=first[t];~i;i=e[i].next)if(e[i^1].c)f=0;
	if(!f)return puts("-1"),0;
	else cout<<ans;
	return 0;
}

熊猫

codeforces1045H
跟这道题一毛一样


鸽子

codeforces780H
考试的时候只想到了用均匀撒点水掉了 24 p t s 24pts 24pts
然而正解就是二分一下然后把所有的可形区域映射到 [ 0 , c m ] [0,\frac cm] [0,mc]上看有没有一个点被覆盖等于 m m m次。
嘴巴ac
O r z Orz Orz了一波其他神犇的代码:

#include
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return (ib==ob)?-1:*ib++;
}
inline int read(){
	int ans=0;
	bool f=1;
	char ch=gc();
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return f?ans:-ans;
}
const int N=1e5+5;
const double eps=1e-9;
int n,m,num,cnt;
double len[N],sum=0,A,B,C;
inline double sqr(double x){return x*x;}
struct pot{
	double x,y;
	pot(double x=0,double y=0):x(x),y(y){}
	friend inline pot operator+(const pot&a,const pot&b){return pot(a.x+b.x,a.y+b.y);}
	friend inline pot operator-(const pot&a,const pot&b){return pot(a.x-b.x,a.y-b.y);}
	friend inline pot operator*(const pot&a,const double&b){return pot(a.x*b,a.y*b);}
	friend inline pot operator/(const pot&a,const double&b){return pot(a.x/b,a.y/b);}
	inline double mod(){return sqr(x)+sqr(y);}
}a[N],dir[N],st,ed;
inline double dist(pot a,pot b){return sqrt((a-b).mod());}
struct F{double ql,qr,a,b,c;}f[N<<4];
struct Data{
	double pos;
	int v;
	friend inline bool operator<(const Data&a,const Data&b){return fabs(a.pos-b.pos)<eps?a.v<b.v:a.pos<b.pos;}
}t[N<<4];
inline bool check(double lim){
	cnt=0;
	double l,r,z,x,y;
	for(ri i=1;i<=num;++i){
		A=f[i].a,B=f[i].b,C=f[i].c-lim;
		l=f[i].ql,r=f[i].qr;
		if(fabs(A)<eps){
			if(fabs(B)<eps){if(C<eps)t[++cnt]=(Data){l,1},t[++cnt]=(Data){r,-1};}
			else{
			  z=-C/B;
			  if(B>0&&z>0)t[++cnt]=(Data){l,1},t[++cnt]=(Data){min(l+z,r),-1};
			  else if(B<0&&l+z<r)t[++cnt]=(Data){max(l+z,0.0),1},t[++cnt]=(Data){r,-1};
			}
		}
		else{
			z=B*B-4*A*C;
			if(z<0)continue;
			z=sqrt(z),x=(-B-z)/(2*A),y=(-B+z)/(2*A);
			if(l+x>r||y<0) continue;
			t[++cnt]=(Data){l+max(0.0,x),1};
			t[++cnt]=(Data){min(r,l+y),-1};
		}
	}
	sort(t+1,t+cnt+1);
	for(ri i=1,j=0;i<=cnt;++i){
		j+=t[i].v;
		if(j==m)return 1;
	}
	return 0;
}
int main(){
	int pl=1,pr=1,id=1;
	pot dr,dt;
	double l=0,r,mid,res,cur=0,L,R,ave;
	pot st,ed;
	n=read(),m=read();
	for(ri i=1;i<=n;++i)a[i].x=read(),a[i].y=read();
	a[n+1]=a[1];
	for(ri i=1;i<=n;++i){
		len[i]=dist(a[i],a[i+1]);
		dir[i]=(a[i+1]-a[i])/len[i];
		sum+=len[i];
	}
	ave=R=sum/m;
	for(;len[pr]<R+eps;++pr)R-=len[pr];
	st=a[1],ed=a[pr]+dir[pr]*R;
	L=len[1],R=len[pr]-R;
	for(;cur+(1e-5)<sum;){
		res=min(id*ave-cur,min(L,R));
		dt=ed-st,dr=dir[pr]-dir[pl];
		f[++num]=(F){cur-(id-1)*ave,cur-(id-1)*ave+res,dr.mod(),2*(dr.x*dt.x+dr.y*dt.y),dt.mod()};
		cur+=res;
		if(cur+(1e-5)>id*ave)id++;
		st=st+(dir[pl]*res),ed=ed+(dir[pr]*res);
		if(res+eps>L)pl=pl%n+1,L=len[pl];
		else L-=res;
		if(res+eps>R)pr=pr%n+1,R=len[pr];
		else R-=res;
	}
	for(r=ave;r-l>eps;)mid=(l+r)/2.0,check(mid*mid)?r=mid:l=mid;
	printf("%.8lf",l);
	return 0;
}

你可能感兴趣的:(#,题解)