对于三个点 a b c 有两个边权 x y
有结论 min( (a+b)/x , (b+c)/y ) < (a+b+c)/(x+y)
由结论推广出去 三个点一定比四个点优 四个点一定比五个点优 ...............
我们可以得到结论 由两个点和一个边权得到的值最优
1 #include <cstdio> 2 #include <cctype> 3 #include <vector> 4 5 const int MAXN=100010; 6 7 int n,m; 8 9 int a[MAXN]; 10 11 struct node { 12 int to; 13 int val; 14 node(int to,int val):to(to),val(val) {} 15 }; 16 17 std::vector<node> Graph[MAXN]; 18 19 inline void read(int&x) { 20 int f=1;register char c=getchar(); 21 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 22 for(;isdigit(c);x=x*10+c-48,c=getchar()); 23 x=x*f; 24 } 25 26 int hh() { 27 freopen("graph.in","r",stdin); 28 freopen("graph.out","w",stdout); 29 read(n);read(m); 30 for(int i=1;i<=n;++i) read(a[i]); 31 for(int x,y,v,i=1;i<=m;++i) { 32 read(x);read(y);read(v); 33 Graph[x].push_back(node(y,v)); 34 Graph[y].push_back(node(x,v)); 35 } 36 double ans=.0; 37 for(int i=1;i<=n;++i) { 38 for(int j=0;j<Graph[i].size();++j) { 39 int v=Graph[i][j].to; 40 double val=(double)(a[i]+a[v])/Graph[i][j].val; 41 if(ans<val) ans=val; 42 } 43 } 44 printf("%.2lf\n",ans); 45 fclose(stdin); 46 fclose(stdout); 47 return 0; 48 } 49 50 int sb=hh(); 51 int main(int argc,char**argv) {;}
贪心 枚举高度 统计最小的宽度
当身高>x 宽度<=x 一定躺下
身高<=x 宽度>x 一定不会躺下
当身高,宽度<=x
1丶 身高>宽度 一定不躺下
2丶 可以躺下 宽度-身高的值越大越好 (记录sort取大的数)
1 #include <cstdio> 2 #include <cctype> 3 #include <algorithm> 4 5 const int MAXN=1010; 6 7 int n,ans,sum; 8 9 int w[MAXN],h[MAXN],data[MAXN],Nw[MAXN],Nh[MAXN]; 10 11 inline void read(int&x) { 12 int f=1;register char c=getchar(); 13 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 14 for(;isdigit(c);x=x*10+c-48,c=getchar()); 15 x=x*f; 16 } 17 18 bool cmp(int a,int b) {return a>b;} 19 20 int check(int x) { 21 int Alter=0,tot=0; 22 for(int i=1;i<=n;++i) { 23 if(h[i]<=x) { 24 Nw[i]=w[i],Nh[i]=h[i]; 25 if(h[i]<w[i]) { 26 if(w[i]>x) continue; 27 data[++tot]=Nw[i]-Nh[i]; 28 } 29 } 30 else { 31 if(w[i]>x) return false; 32 if(Alter==n/2) return false; 33 Alter++,Nw[i]=h[i],Nh[i]=w[i]; 34 } 35 } 36 std::sort(data+1,data+1+tot,cmp); 37 sum=0; 38 tot=n/2-Alter; 39 for(int i=1;i<=n;++i) sum+=Nw[i]; 40 for(int i=1;i<=tot;++i) sum-=data[i]; 41 return sum; 42 } 43 44 int hh() { 45 freopen("photo.in","r",stdin); 46 freopen("photo.out","w",stdout); 47 read(n); 48 ans=1e9; 49 for(int i=1;i<=n;++i) read(w[i]),read(h[i]); 50 for(int i=1;i<=1000;++i) { 51 int Len=check(i); 52 if(Len) ans=ans>i*Len?Len*i:ans; 53 } 54 printf("%d",ans); 55 return 0; 56 } 57 58 int sb=hh(); 59 int main(int argc,char**argv) {;}
套路。。
每次都是2^n 变成 2^(n-1) 这就是线段树从底层向上返回值的变化啊!
只需要维护一个flag 表示当前层是什么操作
1 #include <cstdio> 2 #include <cctype> 3 4 const int MAXN=200010; 5 6 int n,q,k; 7 8 int a[MAXN]; 9 10 struct node { 11 int l,r; 12 int sum; 13 }; 14 node t[MAXN<<2]; 15 16 inline void read(int&x) { 17 int f=1;register char c=getchar(); 18 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 19 for(;isdigit(c);x=x*10+c-48,c=getchar()); 20 x=x*f; 21 } 22 23 void build_tree(int now,int l,int r,int flag) { 24 t[now].l=l;t[now].r=r; 25 if(l==r) { 26 t[now].sum=a[l]; 27 return; 28 } 29 int mid=(l+r)>>1; 30 build_tree(now<<1,l,mid,flag^1); 31 build_tree(now<<1|1,mid+1,r,flag^1); 32 if(flag) t[now].sum=t[now<<1].sum|t[now<<1|1].sum; 33 else t[now].sum=t[now<<1].sum^t[now<<1|1].sum; 34 return; 35 } 36 37 void modify(int now,int pos,int v,int flag) { 38 if(t[now].l==t[now].r) { 39 t[now].sum=v; 40 return; 41 } 42 int mid=(t[now].l+t[now].r)>>1; 43 if(pos<=mid) modify(now<<1,pos,v,flag^1); 44 else modify(now<<1|1,pos,v,flag^1); 45 if(flag) t[now].sum=t[now<<1].sum|t[now<<1|1].sum; 46 else t[now].sum=t[now<<1].sum^t[now<<1|1].sum; 47 return; 48 } 49 50 int hh() { 51 freopen("xor.in","r",stdin); 52 freopen("xor.out","w",stdout); 53 read(k);read(q); 54 n=1; 55 for(int i=1;i<=k;++i) n*=2; 56 for(int i=1;i<=n;++i) read(a[i]); 57 build_tree(1,1,n,k&1); 58 for(int x,y,i=1;i<=q;++i) { 59 read(x);read(y); 60 modify(1,x,y,k&1); 61 printf("%d\n",t[1].sum); 62 } 63 fclose(stdin); 64 fclose(stdout); 65 return 0; 66 } 67 68 int sb=hh(); 69 int main(int argc,char**argv) {;}