【模拟赛】2020.4.29

  • 全场除了我都200+,就我一个刚过100/kk

T1 一道图论好题(graph)
考场上打了个暴力还只有20pts,我菜死了。(除数没判0)
显然,选两个点最优。
证明:
我们先找到两个点 \(X,Y\) 他俩之间的边权为 \(a\),使得整张图中没有两个点的点权之和比边权大于 \(\frac{X+Y}{a}\),如下图。

我们再添加一个点 \(Z\)\(Z\)\(Y\) 之间的边为 \(b\) 如下图。

\(\Large\because \frac{X+Y}{a} > \frac{Y+Z}{b}\)

\(\Large\therefore \frac{bX+bY}{ab} > \frac{aY+aZ}{ab}\)

$\Large\therefore bX+bY > aY+aZ $

想要证明选两个点最优只要证明 \(\frac{X+Y}{a} > \frac{X+Y+Z}{a+b}\) 即可。

\(\Large \because \frac{X+Y}{a} > \frac{X+Y+Z}{a+b}\)

\(\Large \therefore \frac{aX+aY+bX+bY}{a(a+b)} > \frac{aX+aY+aZ}{a(a+b)}\)

\(\Large \therefore aX+aY+bX+bY > aX+aY+aZ\)

\(\Large \therefore bX+bY > aZ\)

所以只要证 \(bX+bY > aZ\) 即可,因为前面已经知道了 \(bX+bY > aY+aZ\),显然 \(bX+bY > aZ\)

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<iomanip>

inline void read(int &T) {
	int x=0;bool f=0;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=!f;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	T=f?-x:x;
}

int n,m,a[100001];
double ans;

int main() {
	read(n),read(m);
	for(int i=1;i<=n;++i) read(a[i]);
	for(int i=1,u,v,w;i<=m;++i) {
		read(u),read(v),read(w);
		ans=std::max(ans,(a[u]+a[v])*1.0/w*1.0);
	}
	std::cout<<std::fixed<<std::setprecision(2)<<ans<<'\n';
	return 0;
}

T2拍照(photo)
注意到 \(n \leq 1000\)所以我们枚举出现过的数作为高,当高一定时,宽越小越好,贪心的去选择,感觉细节有点多,调了有3小时/kk。

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>

inline void read(int &T) {
	int x=0;bool f=0;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=!f;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	T=f?-x:x;
}

int n,cnt,num[1001];
bool appear[1001],used[1001];
bool appearh[1001],appearw[1001];
int minnh[1001];
int maxh,sumw,ans=2147483647;
struct People {
	int w,h,num;
	friend bool operator<(People x,People y) {
		return x.h>y.h;
	}
}a[1001],b[1001];

bool cmp(People x,People y) {
	return (x.w-x.h)>(y.w-y.h);
}

int main() {
	read(n);
	for(int i=1;i<=n;++i) {
		read(a[i].w),read(a[i].h);
		if(minnh[a[i].w]==0) minnh[a[i].w]=i;
		else if(a[minnh[a[i].w]].h>a[i].h) minnh[a[i].w]=i;
		appearw[a[i].w]=1;
		appearh[a[i].h]=1;
		if(!appear[a[i].w]) {
			num[++cnt]=a[i].w;
			appear[a[i].w]=1;
		}
		if(!appear[a[i].h]) {
			num[++cnt]=a[i].h;
			appear[a[i].h]=1;
		}
		a[i].num=i;
	}
	for(int i=1;i<=cnt;++i) {
		for(int j=1;j<=n;++j) b[j]=a[j];
		memset(used,0,sizeof used);
		int sumw=0,fzn=n/2;bool flag=1;
		if(!appearh[num[i]]) {
			std::swap(b[minnh[num[i]]].w,b[minnh[num[i]]].h);
			--fzn;
		}
		std::sort(b+1,b+n+1);
		for(int j=1;j<=n;++j) {
			if(b[j].w>num[i]&&b[j].h>num[i]) {flag=0;break;}
			if(b[j].w>num[i]) used[b[j].num]=1,sumw+=b[j].w;
			else if(b[j].h>num[i]) used[b[j].num]=1,sumw+=b[j].h,--fzn;
			else if(fzn!=0) break;
			else if(fzn==0) used[b[j].num]=1,sumw+=b[j].w;
			if(fzn<0) {flag=0;break;}
		}
		std::sort(b+1,b+n+1,cmp);
		for(int j=1;j<=n;++j) {
			if(used[b[j].num]) continue;
			if(b[j].w>num[i]) used[b[j].num]=1,sumw+=b[j].w;
			else if(b[j].w>b[j].h&&fzn) used[b[j].num]=1,--fzn,sumw+=b[j].h;
			else used[b[j].num]=1,sumw+=b[j].w;
		}
		if(!flag) continue;
		ans=std::min(ans,sumw*num[i]);
	}
	std::cout<<ans<<'\n';
	return 0;
}

T3或和异或(xor)
很容易想到用线段树维护,对于线段树的最后一层我们给他个 \(type=1\) ,上一层的 \(type\) 等于这一层的取非即可,对于 \(type=0\) 这一层的值由下一层左右儿子或起来的到,对于 \(type=1\) 这一层的值由下一层左右儿子异或起来的到。

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#define MAXN 140001
#define lson now<<1
#define rson now<<1|1

inline void read(int &T) {
	int x=0;bool f=0;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=!f;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	T=f?-x:x;
}

int n,q;
struct Node {
	int l,r,w,t;
}tree[MAXN<<2];


int qpow(int b) {
	int ans=1,base=2;
	while(b) {
		if(b&1) ans*=base;
		base*=base;
		b>>=1;
	}
	return ans;
}

void build(int l,int r,int now) {
	tree[now].l=l,tree[now].r=r;
	if(tree[now].l==tree[now].r) {
		read(tree[now].w);
		tree[now].t=1;return;
	}
	int mid=(tree[now].l+tree[now].r)>>1;
	build(l,mid,lson),build(mid+1,r,rson);
	tree[now].t=!tree[lson].t;
	if(tree[now].t) tree[now].w=tree[lson].w^tree[rson].w;
	else tree[now].w=tree[lson].w|tree[rson].w;
}

void update(int x,int k,int now) {
	if(tree[now].l==tree[now].r) {
		tree[now].w=k;return;
	}
	int mid=(tree[now].l+tree[now].r)>>1;
	if(x<=mid) update(x,k,lson);
	else update(x,k,rson);
	if(tree[now].t) tree[now].w=tree[lson].w^tree[rson].w;
	else tree[now].w=tree[lson].w|tree[rson].w;
}

int main() {
	read(n),read(q);int len=qpow(n);
	build(1,len,1);
	for(int i=1,x,y;i<=q;++i) {
		read(x),read(y);
		update(x,y,1);
		printf("%d\n",tree[1].w);
	}
	return 0;
}
posted @ 2020-04-29 19:07  yu__xuan  阅读(176)  评论(0编辑  收藏  举报