北京集训②DAY1 Afternoon

对于三个点 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) {;}
代码

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值