- 全场除了我都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;
}