zoukankan      html  css  js  c++  java
  • 【模拟赛】2020.4.29

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

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

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

    (Largeecause frac{X+Y}{a} > frac{Y+Z}{b})

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

    $Large herefore bX+bY > aY+aZ $

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

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

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

    (Large herefore aX+aY+bX+bY > aX+aY+aZ)

    (Large herefore 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<<'
    ';
    	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<<'
    ';
    	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
    ",tree[1].w);
    	}
    	return 0;
    }
    
  • 相关阅读:
    四、java IO--使用字节流拷贝文件
    三、java IO--使用字节流写入文件
    二、java IO--使用字节流读取文件
    一、java--IO概念
    xml解析/读取--dom4j
    java程序执行顺序
    Flask学习——cookie操作
    Linux13 shell函数、数组及awk、awk中的数组
    Linux12 RPM 和yum的使用
    Linux11 IP网段划分及主机接入网络
  • 原文地址:https://www.cnblogs.com/poi-bolg-poi/p/12804071.html
Copyright © 2011-2022 走看看