• 2017-10-01-afternoon


    T1 一道图论好题(graph)

    Time Limit:1000ms   Memory Limit:128MB

    题目描述

    LYK有一张无向图G={V,E},这张无向图有n个点m条边组成。并且这是一张带权图,不仅有边权还有点权。

    LYK给出了一个子图的定义,一张图G’={V’,E’}被称作G的子图,当且仅当

    ·G’的点集V’包含于G的点集V。

    ·对于E中的任意两个点a,b∈V’,当(a,b)∈E时,(a,b)一定也属于E’,并且连接这两个点的边的边权是一样的。

    LYK给一个子图定义了它的价值,它的价值为:点权之和与边权之和的比。 看

    LYK想找到一个价值最大的非空子图,所以它来找你帮忙啦。

    输入格式(graph.in)

        第一行两个数n,m表示一张n个点m条边的图。

        第二行n个数ai表示点权。

        接下来m行每行三个数u,v,z,表示有一条连接u,v的边权为z的无向边。数据保证任意两个点之间最多一条边相连,并且不存在自环。

    输出格式(graph.out)

    你需要输出这个价值最大的非空子图的价值,由于它是一个浮点数,你只需要保留小数点后两位有效数字。

    输入样例

    3 3

    2 3 4

    1 2 3

    1 3 4

    2 3 5

    输出样例

    1.67

    样例解释

    选择1,2两个点,则价值为5/3=1.67。

    对于20%的数据n=2

    对于50%的数据n<=5

    对于100%的数据1<=n,m<=100000,1<=ai,z<=1000。

     大忽悠题。。

     1 /*
     2 设点1,2,之间边权w12,点2,3,之间边权w23
     3 假设 t1=(v1+v2)/w12>(v2+v3)/w23,即
     4       v1*w23+v2*w23>v2*w12+v3*w12
     5 那么 如果在1,2这个图里再加上3这个点
     6      t2==(v1+v2+v3)/(w12+w23)
     7 如果 t1>t2   移项一下就是
     8      v1*w12+v1*w23+v2*w12+v2*w23>v1*w12+v2*w12+v3*w12
     9 又因为v1*w23+v2*w23>v2*w12+v3*w12
    10 所以t1>t2显然,所以就是找两个点的图
    11 */
    12 #include <cstdio>
    13 
    14 #define max(a,b) (a>b?a:b)
    15 
    16 inline void read(int &x)
    17 {
    18     x=0; register char ch=getchar();
    19     for(; ch>'9'||ch<'0'; ) ch=getchar();
    20     for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
    21 }
    22 const int N(100005);
    23 int n,m,val[N];
    24 double ans;
    25 
    26 int Presist()
    27 {
    28 //    freopen("graph.in","r",stdin);
    29 //    freopen("graph.out","w",stdout);
    30     read(n),read(m);
    31     for(int i=1; i<=n; ++i) read(val[i]);
    32     for(int u,v,w; m--; )
    33     {
    34         read(u),read(v),read(w);
    35         ans=max(ans,1.0*(val[u]+val[v])/w);
    36     }
    37     printf("%.2lf",ans);
    38     return 0;
    39 }
    40 
    41 int Aptal=Presist();
    42 int main(int argc,char**argv){;} 
    AC

    T2 拍照(photo)

    Time Limit:1000ms   Memory Limit:128MB

    题目描述

        假设这是一个二次元。

    LYK召集了n个小伙伴一起来拍照。他们分别有自己的身高Hi和宽度Wi。

    为了放下这个照片并且每个小伙伴都完整的露出来,必须需要一个宽度为ΣWi,长度为max{Hi}的相框。(因为不能叠罗汉)。

    LYK为了节省相框的空间,它有了绝妙的idea,让部分人躺着!一个人躺着相当于是身高变成了Wi,宽度变成了Hi。但是很多人躺着不好看,于是LYK规定最多只有n/2个人躺着。(也就是说当n=3时最多只有1个人躺着,当n=4时最多只有2个人躺着)

    LYK现在想问你,当其中部分人躺着后,相框的面积最少是多少。

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                

    输入格式(photo.in)

        第一行一个数n。

        接下来n行,每行两个数分别是Wi,Hi。

    输出格式(photo.out)

    你需要输出这个相框的面积最少是多少。

    输入样例

    3

    3 1

    2 2

    4 3

    输出样例

    21

    样例解释

    如果没人躺过来,需要27的面积。

    我们只要让第1个人躺过来,就只需要21的面积!

    对于30%的数据n<=10。

    对于60%的数据n<=1000,Wi,Hi<=10。

    对于100%的数据1<=n,Wi,Hi<=1000。

     1 /*
     2 气人诶。。。
     3 一开始二分高度,,然后WA3个点。
     4 然后高度从大到小枚举,就A了。 
     5 
     6 对于每个人,判断在当前高度下是否需要躺下,且躺下是否合法
     7 当所有人的高度都符合要求时,如果还有让人躺下的次数
     8 判断每个人在躺下后,是否比站着更优 (sort一下方便) 
     9 */
    10 #include <algorithm>
    11 #include <cstdio>
    12 
    13 #define max(a,b) (a>b?a:b)
    14 
    15 inline void read(int &x)
    16 {
    17     x=0; register char ch=getchar();
    18     for(; ch>'9'||ch<'0'; ) ch=getchar();
    19     for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
    20 }
    21 const int N(1e3+5);
    22 int n,W,H;
    23 struct People {
    24     int w,h;
    25     bool operator < (const People&x)const
    26     {
    27         return w-h>x.w-x.h;
    28 //        if(h!=x.h) return h>x.h;
    29 //        return w<x.w;
    30     }
    31 }peo[N];
    32 
    33 int l,r,mid,ans=0x7fffffff,tmp;
    34 inline bool check(int nowh)
    35 {
    36     int cnt=n>>1,ret=0,sw=W;
    37     for(int i=1; i<=n; ++i)
    38      if(peo[i].h>nowh)
    39      {
    40          sw-=peo[i].w;
    41          sw+=peo[i].h;
    42          if(peo[i].w>nowh) return 0;
    43         if(--cnt<0) return 0;
    44      }
    45     for(int i=1; cnt&&i<=n; ++i)
    46       if(peo[i].h<=nowh&&peo[i].h<peo[i].w&&peo[i].w<=nowh)
    47         sw-=peo[i].w,sw+=peo[i].h,cnt--;
    48     if(tmp*nowh<ans) tmp=sw; return tmp*nowh<ans;
    49 }
    50 
    51 int Presist()
    52 {
    53     freopen("photo.in","r",stdin);
    54     freopen("photo.out","w",stdout);
    55     read(n);
    56     for(int i=1; i<=n; ++i)
    57     {
    58         read(peo[i].w),read(peo[i].h);
    59         W+=peo[i].w;H=max(H,peo[i].h);
    60     }
    61     std::sort(peo+1,peo+n+1);
    62     for(; check(H); H--) ans=H*tmp;
    63     /*for(r=H; l<=r; )
    64     {
    65         mid=l+r>>1;
    66         if(check(mid))
    67         {
    68             ans=mid*tmp;
    69             r=mid-1;
    70         }
    71         else l=mid+1;
    72     }*/
    73     printf("%d
    ",ans);
    74     return 0;
    75 }
    76 
    77 int Aptal=Presist();
    78 int main(int argc,char**argv){;}
    枚举+贪心AC

    T3 或和异或(xor)

    Time Limit:2000ms   Memory Limit:128MB

    题目描述

    LYK最近在研究位运算,它研究的主要有两个:or和xor。(C语言中对于|和^)

    为了更好的了解这两个运算符,LYK找来了一个2^n长度的数组。它第一次先对所有相邻两个数执行or操作,得到一个2^(n-1)长度的数组。也就是说,如果一开始时a[1],a[2],…,a[2^n],执行完第一次操作后,会得到a[1] or a[2],a[3] or a[4] ,…, a[(2^n)-1] or a[2^n]。

    第二次操作,LYK会将所有相邻两个数执行xor操作,得到一个2^(n-2)长度的数组,假如第一次操作后的数组是b[1],b[2],…,b[2^(n-1)],那么执行完这次操作后会变成b[1] xor b[2], b[3] xor b[4] ,…, b[(2^(n-1))-1] xor b[2^(n-1)]。

    第三次操作,LYK仍然将执行or操作,第四次LYK执行xor操作。如此交替进行。

    最终这2^n个数一定会变成1个数。LYK想知道最终这个数是多少。

    为了让这个游戏更好玩,LYK还会执行Q次修改操作。每次修改原先的2^n长度的数组中的某一个数,对于每次修改操作,你需要输出n次操作后(最后一定只剩下唯一一个数)剩下的那个数是多少。

    输入格式(xor.in)

        第一行两个数n,Q。

    接下来一行2^n个数ai表示一开始的数组。

    接下来Q行,每行两个数xi,yi,表示LYK这次的修改操作是将a{xi}改成yi。

    输出格式(xor.out)

    Q行,表示每次修改操作后执行n次操作后剩下的那个数的值。

    输入样例

    2 4

    1 6 3 5

    1 4

    3 4

    1 2

    1 2

    输出样例

    1

    3

    3

    3

    样例解释

    第一次修改,{4,6,3,5}->{6,7}->{1}

    第二次修改,{4,6,4,5}->{6,5}->{3}

    第三次修改,{2,6,4,5}->{6,5}->{3}

    第四次修改,{2,6,4,5}->{6,5}->{3}

    对于30%的数据n<=17,Q=1。

    对于另外20%的数据n<=10,Q<=1000。

    对于再另外30%的数据n<=12,Q<=100000。

    对于100%的数据1<=n<=17,1<=Q<=10^5,1<=xi<=2^n,0<=yi<2^30,0<=ai<2^30。

     1 #include <cstdio>
     2 
     3 inline void read(int &x)
     4 {
     5     x=0; register char ch=getchar();
     6     for(; ch>'9'||ch<'0'; ) ch=getchar();
     7     for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
     8 }
     9 const int N(5e6+5);
    10 int n,q,a[N],x[N];
    11 
    12 inline int work()
    13 {
    14     int cnt1=0,cnt2=1<<n;
    15     for(int i=1; i<=1<<n; ++i) x[i]=a[i];
    16     for(; 1; )
    17     {
    18         cnt1=0;
    19         for(int i=1; i<=cnt2; i+=2)
    20             x[++cnt1]=x[i]|x[i+1];
    21         if(cnt1==1) return x[1];
    22         cnt2=0;
    23         for(int i=1; i<=cnt1; i+=2)
    24             x[++cnt2]=x[i]^x[i+1];
    25         if(cnt2==1) return x[1];
    26     }
    27     
    28 }
    29 
    30 int Presist()
    31 {
    32 //    freopen("xor.in","r",stdin);
    33 //    freopen("xor.out","w",stdout);
    34     read(n),read(q);
    35     for(int i=1; i<=1<<n; ++i) read(a[i]);
    36     for(int pos,num; q--; )
    37     {
    38         read(pos),read(num);
    39         a[pos]=num;
    40         printf("%d
    ",work());
    41     }
    42     return 0;
    43 }
    44 
    45 int Aptal=Presist();
    46 int main(int argc,char**argv){;}
    搞笑的50分暴力
     1 /*
     2 数的个数依次减少,每次有类似操作——>>线段树维护
     3 对于一个区间,标记他的父亲是需要 | 得到还是 ^ 得到 
     4 */
     5 #include <cstdio>
     6 
     7 inline void read(int &x)
     8 {
     9     x=0; register char ch=getchar();
    10     for(; ch>'9'||ch<'0'; ) ch=getchar();
    11     for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
    12 }
    13 const int N(1<<18);
    14 
    15 struct Tree {
    16     bool flag;
    17     int l,r,mid,val;
    18 }tr[N<<2];
    19 
    20 #define lc (now<<1)
    21 #define rc (now<<1|1)
    22 #define mid (tr[now].l+tr[now].r>>1)
    23 
    24 void Tree_update(int now)
    25 {
    26     tr[now].flag=!tr[lc].flag;
    27     if(!tr[lc].flag)
    28          tr[now].val=tr[lc].val|tr[rc].val;
    29     else tr[now].val=tr[lc].val^tr[rc].val;
    30 }
    31 void Tree_build(int now,int l,int r)
    32 {
    33     tr[now].l=l; tr[now].r=r;
    34     if(l==r) { read(tr[now].val),tr[now].flag=0;return ; }
    35     Tree_build(lc,l,mid);    Tree_build(rc,mid+1,r);
    36     Tree_update(now);
    37 }
    38 void Tree_change(int now,int to,int x)
    39 {
    40     if(tr[now].l==tr[now].r) {tr[now].val=x; return ;}
    41     if(to<=mid) Tree_change(lc,to,x);
    42     else Tree_change(rc,to,x);
    43     Tree_update(now);
    44 }
    45 
    46 int Presist()
    47 {
    48     freopen("xor.in","r",stdin);
    49     freopen("xor.out","w",stdout);
    50     int n,q;    read(n),read(q);
    51     Tree_build(1,1,1<<n);
    52     for(int pos,num; q--; )
    53     {
    54         read(pos),read(num);
    55         Tree_change(1,pos,num);
    56         printf("%d
    ",tr[1].val);
    57     }
    58     return 0;
    59 }
    60 
    61 int Aptal=Presist();
    62 int main(int argc,char**argv){;}
    线段树 AC
     1 #include <cmath>
     2 #include <cstdio>
     3 #include <iostream>
     4 #include <cstdlib>
     5 #include <algorithm>
     6 #include <string>
     7 #include <cstring>
     8 using namespace std;
     9 long long st[131073][18];
    10 int next[18][131073],i,j,n,m,now,k,A,B;
    11 int main()
    12 {
    13     freopen("xor.in","r",stdin);
    14     freopen("xor.out","w",stdout);
    15     scanf("%d%d",&n,&m);
    16     for (i=1; i<=(1<<n); i++) cin>>st[i][0];
    17     for (i=1; i<=n; i++)
    18     {
    19         for (j=1; j<=(1<<n); j+=(1<<i))
    20         {
    21             if (i % 2==1) st[j][i]=st[j][i-1]|st[j+(1<<(i-1))][i-1]; else
    22               st[j][i]=st[j][i-1]^st[j+(1<<(i-1))][i-1];
    23         }
    24     }
    25     for (i=1; i<=n; i++)
    26       for (j=1; j<=(1<<n); j+=(1<<i))
    27       {
    28           for (k=j; k<=j+(1<<i)-1; k++)
    29             next[i][k]=j;
    30       }
    31     for (i=1; i<=m; i++)
    32     {
    33         scanf("%d%d",&A,&B);
    34         st[A][0]=B;
    35         for (j=1; j<=n; j++)
    36         {
    37             now=next[j][A];
    38             if (j % 2==1) st[now][j]=st[now][j-1]|st[now+(1<<(j-1))][j-1]; else
    39                 st[now][j]=(st[now][j-1]^st[now+(1<<(j-1))][j-1]);
    40         }
    41         cout<<st[1][n]<<endl;
    42     }
    43     return 0;
    44 }
    std的set表
    ——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。
  • 相关阅读:
    2019 SDN阅读作业
    第10组 Alpha冲刺(4/6)
    第10组 Alpha冲刺(3/6)
    2019 SDN上机第3次作业
    团队Beta4
    团队Beta3
    团队Beta2
    团队Beta1
    tuandui last
    团队Arpha6
  • 原文地址:https://www.cnblogs.com/Shy-key/p/7647661.html
Copyright © 2020-2023  润新知