zoukankan      html  css  js  c++  java
  • Minieye杯第十五届华中科技大学程序设计邀请赛网络赛 部分题目

    链接:https://pan.baidu.com/s/12gSzPHEgSNbT5Dl2QqDNpA
    提取码:fw39
    复制这段内容后打开百度网盘手机App,操作更方便哦

    D    Grid

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <set>
     8 #include <map>
     9 #include <queue>
    10 #include <iostream>
    11 using namespace std;
    12 
    13 #define ll long long
    14 
    15 const int maxn=2e2+10;
    16 const int inf=1e9;
    17 const double eps=1e-8;
    18 
    19 char s[maxn][maxn];
    20 
    21 int main()
    22 {
    23     int h,w,n,m,i,j,x,y;
    24     scanf("%d%d%d",&h,&w,&n);
    25     m=(h*w+1)/2;
    26     if (n>m)
    27         printf("-1");
    28     else
    29     {
    30         for (i=0;i<h;i++)
    31             for (j=0;j<w;j++)
    32                 s[i][j]='*';
    33         x=0,y=0;
    34         while (n--)
    35         {
    36             s[x][y]='#';
    37             y+=2;
    38             if (y>=w)
    39             {
    40                 x++;
    41                 if (s[x-1][0]=='#')
    42                     y=1;
    43                 else
    44                     y=0;
    45             }
    46         }
    47             for (i=0;i<h;i++)
    48             {
    49                 for (j=0;j<w;j++)
    50                     printf("%c",s[i][j]);
    51                 printf("
    ");
    52             }
    53     }
    54     return 0;
    55 }
    56 /*
    57 
    58 */

    G    Multithread

    模拟

    inf long long

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <set>
     8 #include <map>
     9 #include <queue>
    10 #include <iostream>
    11 using namespace std;
    12 
    13 #define ll long long
    14 
    15 const int maxn=1e6+10;
    16 const ll inf=1e18;
    17 const double eps=1e-15;
    18 
    19 ll a[maxn],c[maxn],t=0;
    20 
    21 int main()
    22 {
    23     int n,i,j;
    24     double z;
    25     scanf("%d",&n);
    26     for (i=1;i<=n;i++)
    27         scanf("%lld",&a[i]);
    28     sort(a+1,a+n+1);
    29     a[n+1]=inf;
    30     j=1;
    31     for (i=1;i<=n;i++)
    32     {
    33         while (a[j]==a[i])
    34             j++;
    35         c[i]=a[j];
    36     }
    37     for (i=1;i<=n;i++)
    38     {
    39         t=max(t,a[i]);
    40         if (t>=c[i])
    41         {
    42             printf("0");
    43             return 0;
    44         }
    45         t+=ceil(sqrt(a[i]));
    46     }
    47     printf("1");
    48     return 0;
    49 }
    50 /*
    51 4
    52 10 11 17 18
    53 
    54 4
    55 10 11 18 18 24
    56 
    57 5
    58 0 0 0 3 4
    59 
    60 10
    61 1000000000 1000000000 1000000000 1000000000 1000000000
    62 1000000000 1000000000 1000000000 1000000000 1000000000
    63 */

    I    Tree

    贪心,一颗子树的权值和大于某个值则使用该子树,否则该子树必定被子树根的父亲使用。

    其实上界可以为sum(c[i])/k,但二分,也节省不了几次操作。

    注意long long,莫名其妙地使用“ll*”失效了,所以我输入的变量的类型设置为long long。

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <set>
     8 #include <map>
     9 #include <queue>
    10 #include <iostream>
    11 using namespace std;
    12 
    13 #define ll long long
    14 
    15 const int maxn=1e5+10;
    16 const int inf=1e9;
    17 const double eps=1e-8;
    18 
    19 struct node
    20 {
    21     int d;
    22     node *to;
    23 }*e[maxn];
    24 
    25 ll c[maxn],sum[maxn],m;
    26 bool vis[maxn];
    27 int g=0;
    28 
    29 void dfs(int d)
    30 {
    31     vis[d]=1;
    32     node *p=e[d];
    33     sum[d]+=c[d];
    34     while (p)
    35     {
    36         if (!vis[p->d])
    37         {
    38             dfs(p->d);
    39             sum[d]+=sum[p->d];
    40         }
    41         p=p->to;
    42     }
    43     if (sum[d]>=m)
    44         g++,sum[d]=0;
    45 }
    46 
    47 int main()
    48 {
    49     node *p;
    50     int x,y,i;
    51     ll n,k,l,r;
    52     scanf("%lld%lld",&n,&k);
    53     for (i=1;i<n;i++)
    54     {
    55         scanf("%d%d",&x,&y);
    56         p=new node();
    57         p->d=y;
    58         p->to=e[x];
    59         e[x]=p;
    60 
    61         p=new node();
    62         p->d=x;
    63         p->to=e[y];
    64         e[y]=p;
    65     }
    66     for (i=1;i<=n;i++)
    67         scanf("%lld",&c[i]);
    68     l=1,r=100000*n/k;
    69     while (l<=r)
    70     {
    71         m=(l+r)>>1;
    72         g=0;
    73         memset(vis,0,sizeof(vis));
    74         memset(sum,0,sizeof(sum));
    75         dfs(1);
    76         if (g>=k)
    77             l=m+1;
    78         else
    79             r=m-1;
    80     }
    81     printf("%lld",r);
    82     return 0;
    83 }
    84 /*
    85 5 5
    86 1 2
    87 1 3
    88 2 4
    89 2 5
    90 4 4 3 4 5
    91 */

    K    Car

    注意x,y的作用域,减少了不少方案。

    还是那样,想清楚了再编码,验证一下测试样例,造多几个数据。

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <set>
     8 #include <map>
     9 #include <queue>
    10 #include <iostream>
    11 using namespace std;
    12 
    13 #define ll long long
    14 
    15 const int maxn=1e6+10;
    16 const int inf=1e9;
    17 const double eps=1e-8;
    18 
    19 ll f[maxn][2];
    20 
    21 int main()
    22 {
    23     char ch;
    24     ll a,b,c,d,x=0,y=0,sum=0,v=1<<30;
    25     int n,i;
    26     bool vis=0;
    27     scanf("%d",&n);
    28     for (i=1;i<=n;i++)
    29     {
    30         scanf("
    %c",&ch);
    31         if (ch=='C')
    32         {
    33             scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
    34             sum+=(y+b)*v*2;
    35             sum-=b*(v-(x+a));
    36             x+=a-c;
    37             y+=b-d;
    38             sum-=d*(x+v);
    39             vis=1;
    40         }
    41         else
    42         {
    43             scanf("%lld%lld",&a,&b);
    44             if (!vis)
    45             {
    46                 if (i&1)
    47                     x+=a;
    48                 else
    49                     x-=a;
    50                 sum-=(v-x)*b;
    51                 y+=b;
    52             }
    53             else
    54             {
    55                 if (i&1)
    56                     x-=a;
    57                 else
    58                     x+=a;
    59                 sum-=(x+v)*b;
    60                 y-=b;
    61             }
    62         }
    63     }
    64     printf("%lld",sum);
    65     return 0;
    66 }
    67 /*
    68 4
    69 C 10 10 15 3
    70 B 2 5
    71 A 3 1
    72 B 6 1
    73 
    74 4
    75 C 10 10 15 20
    76 A 10 2
    77 B 6 3
    78 A 1 5
    79 
    80 3
    81 B 100 60
    82 A 30 10
    83 C 50 200 120 30
    84 
    85 4
    86 A 100 60
    87 B 30 50
    88 C 90 700 170 800
    89 B 10 10
    90 */

    J    Another Easy Problem

    比赛时暴力了一发,感觉数值在[1,50]范围内,结果不会太大。看了一下数据,果然,结果<=5,但时间上仍然承受不了。

    方法比较巧妙。其实这种题,要养成往dp想的习惯。。。

    dp,差值可以选择用绝对值表示,因为sum(a[i])<=5000,所以途中,差值最多不超过2500,否则无法再‘’追‘’回来,使差值为0。而数组的第一维,可以使用滚动数组,数组的第二维,其实最多可以开到2500+50即可。

    ( i为已判断i个数,j为差值 f[i][j]为对应的最小未使用数字个数\f[i][j]=min(f[i-1][j]+1,min(f[i-1][j+a],f[i-1][abs(j-a)]) )

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <set>
     8 #include <map>
     9 #include <queue>
    10 #include <iostream>
    11 using namespace std;
    12 
    13 #define ll long long
    14 
    15 const int maxn=1e2+10;
    16 const int maxm=5e3+10;
    17 const int inf=1e9;
    18 const double eps=1e-8;
    19 
    20 int f[maxn][maxm];
    21 
    22 int main()
    23 {
    24     int t,n,a,i,j;
    25     scanf("%d",&t);
    26     while (t--)
    27     {
    28         memset(f,0x3f,sizeof(f));
    29         f[0][0]=0;
    30         scanf("%d",&n);
    31         for (i=1;i<=n;i++)
    32         {
    33             scanf("%d",&a);
    34             for (j=0;j<=2500;j++)
    35                 f[i][j]=min(f[i-1][j]+1,min(f[i-1][j+a],f[i-1][abs(j-a)]));
    36         }
    37         printf("%d
    ",f[n][0]);
    38     }
    39     return 0;
    40 }
    41 /*
    42 5
    43 1 2 4 8 16
    44 
    45 5
    46 1 10 11 30 49
    47 */

    B    Balls

    比赛时考虑到与数学推导有关,没仔细想。

    比赛时应该打表找规律的。哎,其它题写太卡了,耗费大量时间。

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <set>
     8 #include <map>
     9 #include <queue>
    10 #include <iostream>
    11 using namespace std;
    12 
    13 #define ll long long
    14 
    15 const int maxn=1e4+10;
    16 const int inf=1e9;
    17 const double eps=1e-8;
    18 ll sum=0;
    19 
    20 void dfs(int k,int s,ll v)
    21 {
    22     if (k==0)
    23 //    {
    24 //        printf("%lld ",v);
    25         sum+=v;
    26 //    }
    27 
    28     else
    29     {
    30         for (int i=s-k+1;i>=1;i--)
    31             dfs(k-1,s-i,v*i);
    32     }
    33 }
    34 
    35 int main()
    36 {
    37     int k,s;
    38 //    scanf("%d%d",&k,&s);
    39     for (k=1;k<=10;k++)
    40         for (s=1;s<=10;s++)
    41         {
    42             sum=0;
    43             dfs(k,s,1);
    44             printf("%4lld",sum);
    45             if (s==10)
    46                 printf("
    ");
    47             else
    48                 printf(" ");
    49         }
    50     return 0;
    51 }
    52 /*
    53 
    54 */

    如果不熟悉,再打一个组合数学的表。

    方法挺巧妙的!组合数学。

    lucas,直接求逆超时了,求逆初始化,参见代码。

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <set>
     8 #include <map>
     9 #include <queue>
    10 #include <iostream>
    11 using namespace std;
    12 
    13 #define ll long long
    14 
    15 const int maxn=5e6+10;
    16 const int inf=1e9;
    17 const double eps=1e-8;
    18 
    19 ll p,mul[maxn],chu[maxn];
    20 
    21 ll pow(ll a,ll b)
    22 {
    23     ll y=1;
    24     while (b)
    25     {
    26         if (b & 1)
    27             y=y*a%p;
    28         a=a*a%p;
    29         b>>=1;
    30     }
    31     return y;
    32 }
    33 
    34 ll cal(ll n,ll m)
    35 {
    36     if (n<m)
    37         return 0;
    38     ll y=1,i;
    39     if (m+m>n)
    40         m=n-m;
    41     return mul[n]*chu[n-m]%p*chu[m]%p;
    42 //    for (i=1;i<=m;i++)
    43 //        y=y*(n+1-i)%p*pow(i,p-2)%p;
    44     return y;
    45 }
    46 
    47 int main()
    48 {
    49     ll n,m,r,i;
    50     scanf("%lld%lld%lld",&m,&n,&p);
    51     ///init
    52     mul[0]=1;
    53     for (i=1;i<p;i++)
    54         mul[i]=mul[i-1]*i%p;
    55     chu[p-1]=pow(mul[p-1],p-2);
    56     for (i=p-2;i>=1;i--)
    57         chu[i]=chu[i+1]*(i+1)%p;
    58 
    59     n+=m,m*=2;
    60     r=1;
    61     while (m)
    62     {
    63         r=r*cal(n%p,m%p)%p;
    64         n/=p,m/=p;
    65     }
    66     printf("%lld",r);
    67     return 0;
    68 }
    69 /*
    70 
    71 */

    E    Lolita Dress

    组合公式变形

    ( egin{equation*}egin{split}&sum_{n=1}^{min(x,y)}(C_{x}^{n-1}*C_{y}^{n}) \&=sum_{n=1}^{min(x,y)}(C_{x}^{x-n+1}*C_{y}^{n}) \&=C_{x+y}^{x+1}end{split}end{equation*} )

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <set>
     8 #include <map>
     9 #include <queue>
    10 #include <iostream>
    11 using namespace std;
    12 
    13 #define ll long long
    14 
    15 const int maxn=1e6+10;
    16 const int inf=1e9;
    17 const double eps=1e-8;
    18 const ll mod=1e9+7;
    19 
    20 int a[maxn];
    21 ll mul[maxn],chu[maxn];
    22 
    23 ll pow(ll a,ll b)
    24 {
    25     ll y=1;
    26     while (b)
    27     {
    28         if (b&1)
    29             y=y*a%mod;
    30         a=a*a%mod;
    31         b>>=1;
    32     }
    33     return y;
    34 }
    35 
    36 ll cal(ll x,ll y)
    37 {
    38     return mul[x]*chu[y]%mod*chu[x-y]%mod;
    39 }
    40 
    41 int main()
    42 {
    43     ll sum=0;
    44     int n,x=0,y=0,i;
    45     scanf("%d",&n);
    46     mul[0]=1;
    47     for (i=1;i<=n;i++)
    48         mul[i]=mul[i-1]*i%mod;
    49     chu[n]=pow(mul[n],mod-2);
    50     for (i=n-1;i>=0;i--)
    51         chu[i]=chu[i+1]*(i+1)%mod;
    52 
    53     for (i=1;i<=n;i++)
    54     {
    55         scanf("%d",&a[i]);
    56         if (a[i])
    57             y++;
    58     }
    59     for (i=1;i<=n;i++)
    60         if (a[i]==0)
    61         {
    62             sum=(sum+cal(x+y,x+1))%mod;
    63             x++;
    64         }
    65         else
    66             y--;
    67     printf("%lld",sum);
    68     return 0;
    69 }
    70 /*
    71 
    72 */

    A    Wormhole Construction

    之前理解错题意了,只需要求最小的d,不需要最佳的方案(最小边)

    打表找规律

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <set>
      8 #include <map>
      9 #include <queue>
     10 #include <iostream>
     11 using namespace std;
     12 
     13 #define ll long long
     14 
     15 const int maxn=20;
     16 const int inf=1e9;
     17 const double eps=1e-8;
     18 
     19 int n,r;
     20 
     21 struct node
     22 {
     23     int a[maxn][maxn];
     24     node()
     25     {
     26         int i,j;
     27         for (i=1;i<=n;i++)
     28             for (j=1;j<=n;j++)
     29                 a[i][j]=0;
     30     }
     31     node operator*(node y)
     32     {
     33         node z=*this;
     34         int i,j,k;
     35         for (k=1;k<=n;k++)
     36             for (i=1;i<=n;i++)
     37                 for (j=1;j<=n;j++)
     38                     z.a[i][j]|=a[i][k]*y.a[k][j];
     39         return z;
     40     }
     41     int work()
     42     {
     43         node z;
     44         int i,j,l;
     45         z=*this;
     46         for (l=1;l<n;l++)
     47         {
     48             z=z*(*this);
     49             j=1;
     50             for (i=1;i<=n;)
     51             {
     52                 if (i!=j && z.a[i][j]==0)
     53                     break;
     54                 if (j==n)
     55                     i++,j=1;
     56                 else
     57                     j++;
     58             }
     59             if (i==n+1)
     60                 return l;
     61         }
     62         return n;
     63     }
     64 }mat,result;
     65 
     66 void build(int i,int j)
     67 {
     68     int k,v;
     69     ///guess, fasten the speed
     70 //    if (r==2)
     71 //        return;
     72     for (k=1;k>=0;k--)
     73     {
     74         if (k==1 && (i==j || mat.a[j][i]==1))
     75             continue;
     76         mat.a[i][j]=k;
     77         if (j==n)
     78         {
     79             if (i==n)
     80             {
     81                 v=mat.work()+1;
     82                 ///observe
     83                 if (n>=5 && v==2)
     84                 {
     85                     for (int u=1;u<=n;u++)
     86                     {
     87                         for (int v=1;v<=n;v++)
     88                             printf("%d ",mat.a[u][v]);
     89                         printf("
    ");
     90                     }
     91                     printf("
    ");
     92                 }
     93                 if (v<r)
     94                 {
     95                     r=v;
     96                     result=mat;
     97                 }
     98 
     99                 return;
    100             }
    101             build(i+1,1);
    102         }
    103         else
    104             build(i,j+1);
    105     }
    106 }
    107 
    108 int main()
    109 {
    110     for (n=3;n<=10;n++)
    111     {
    112         r=n;
    113         build(1,1);
    114         printf("%d : %d
    ",n,r);
    115 //        for (int i=1;i<=n;i++)
    116 //        {
    117 //            for (int j=1;j<=n;j++)
    118 //                printf("%d ",result.a[i][j]);
    119 //            printf("
    ");
    120 //        }
    121     }
    122     return 0;
    123 }
    124 /*
    125 3 : 2
    126 0 1 0
    127 0 0 1
    128 1 0 0
    129 4 : 3
    130 0 1 1 0
    131 0 0 1 1
    132 0 0 0 1
    133 1 0 0 0
    134 5 : 2
    135 0 1 1 1 0
    136 0 0 1 0 1
    137 0 0 0 1 1
    138 0 1 0 0 1
    139 1 0 0 0 0
    140 6 : 2
    141 0 1 1 1 0 0
    142 0 0 1 1 1 0
    143 0 0 0 1 0 1
    144 0 0 0 0 1 1
    145 1 0 1 0 0 1
    146 1 1 0 0 0 0
    147 7 : 2
    148 0 1 1 1 1 1 0
    149 0 0 1 1 1 0 1
    150 0 0 0 1 0 1 1
    151 0 0 0 0 1 1 1
    152 0 0 1 0 0 1 1
    153 0 1 0 0 0 0 1
    154 1 0 0 0 0 0 0
    155 7 several minutes
    156 */

    就能发现除了4之外,其它的答案都是2。

    就能发现两个比较有意思的解法(当然,这是在已经答案的基础上,尴尬。。。)

    0 1 1 0 0
    0 0 1 1 0
    0 0 0 1 1
    1 0 0 0 1
    1 1 0 0 0
    
    0 1 0 1 1 0
    0 0 0 0 1 1
    1 0 0 0 0 1
    0 1 1 0 0 0
    0 0 1 1 0 0
    1 0 0 0 1 0
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <set>
     8 #include <map>
     9 #include <queue>
    10 #include <iostream>
    11 using namespace std;
    12 
    13 #define ll long long
    14 
    15 const int maxn=1e4+10;
    16 const int inf=1e9;
    17 const double eps=1e-8;
    18 
    19 
    20 
    21 int main()
    22 {
    23     int n,m,i,j,k;
    24     scanf("%d",&n);
    25     if (n==4)
    26     {
    27         printf("3 4
    1 2
    2 3
    3 4
    4 1");
    28         return 0;
    29     }
    30 
    31     if (n&1)
    32     {
    33         m=n>>1;
    34         printf("2 %d
    ",n*m);
    35         for (i=1;i<=n;i++)
    36             for (j=1;j<=m;j++)
    37             {
    38                 k=i+j;
    39                 if (k>n)
    40                     k-=n;
    41                 printf("%d %d
    ",i,k);
    42             }
    43     }
    44     else
    45     {
    46         m=(n-1)>>1;
    47         printf("2 %d
    ",(n-1)*m+4);
    48         for (i=2;i<=n;i++)
    49             for (j=1;j<=m;j++)
    50             {
    51                 k=i+j;
    52                 if (k>n)
    53                     k-=n-1;
    54                 printf("%d %d
    ",i,k);
    55             }
    56         printf("%d %d
    ",1,2);
    57         printf("%d %d
    ",1,2+m+1);
    58         printf("%d %d
    ",3,1);
    59         printf("%d %d
    ",3+m+1,1);
    60     }
    61     return 0;
    62 }
    63 /*
    64 
    65 */

    CA Simple Problem

    O((n*n/2)*n*n*(2m))

    (n*n/2) [i,j]区间

    n [i,j]区间中任意一点 被多算

    2m 可以取到的值

    事实上,n中取任意三点,n*(n-1)*(n-2)/6

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <set>
      8 #include <map>
      9 #include <queue>
     10 #include <iostream>
     11 using namespace std;
     12 
     13 #define ll long long
     14 
     15 const int maxn=32;  ///pay attention
     16 const int maxm=4e3+10;  ///2*m
     17 const int inf=1e9;
     18 const double eps=1e-8;
     19 
     20 struct node1
     21 {
     22     int l,r,x,y;
     23     bool operator<(const node1 &b)
     24     {
     25         return l<b.l;
     26     }
     27 }s1[maxm];
     28 
     29 struct node2
     30 {
     31     int l,r,x,y;
     32     bool operator<(const node2 &b)
     33     {
     34         return r<b.r;
     35     }
     36 }s2[maxm];
     37 
     38 int f[maxn][maxn][maxm],temp[maxn][maxn][maxm],v[maxm],vv[maxm];
     39 int pref[maxn][maxn][maxm],pret[maxn][maxn][maxm],re[maxn],vs[maxm],vt[maxm];
     40 int add[maxm],fan[500000+10];
     41 
     42 void findarr(int i,int j,int g)
     43 {
     44     re[pref[i][j][g]]=v[g];
     45     if (i<=pref[i][j][g]-1)
     46         findarr(i , pref[i][j][g]-1 , pret[i][ pref[i][j][g]-1 ][g]);
     47     if (pref[i][j][g]+1<=j)
     48         findarr(pref[i][j][g]+1 , j , pret[ pref[i][j][g]+1 ][j][g]);
     49 }
     50 
     51 int main()
     52 {
     53     int n,m,g=0,l,r,x,y,c,i,j,k,s,t,value,cnt,sum;
     54     scanf("%d%d",&n,&m);
     55     for (i=1;i<=m;i++)
     56     {
     57         scanf("%d%d%d%d",&l,&r,&x,&y);
     58         vv[i*2-1]=x,vv[i*2]=y;
     59         s1[i]={l,r,x,y};
     60         s2[i]={l,r,x,y};
     61     }
     62     sort(vv+1,vv+m*2+1);    ///m*2
     63     vv[0]=vv[1]-1;
     64     for (i=1;i<=m*2;i++)
     65         if (vv[i]!=vv[i-1])
     66             v[++g]=vv[i];
     67     for (i=1;i<=g;i++)
     68         fan[v[i]]=i;
     69     sort(s1+1,s1+m+1);
     70     sort(s2+1,s2+m+1);
     71     s1[m+1].l=-1,s2[m+1].r=-1;
     72     j=1;
     73     for (i=1;i<=n;i++)  ///n
     74     {
     75         vs[i]=j;
     76         while (s1[j].l==i)
     77             j++;
     78     }
     79     j=1;
     80     for (i=1;i<=n;i++)
     81     {
     82         vt[i]=j;
     83         while (s2[j].r==i-1)
     84             j++;
     85     }
     86 
     87     memset(f,0xff,sizeof(f));///-1
     88     for (c=0;c<n;c++)
     89         for (i=1,j=c+i;j<=n;i++,j++)
     90         {
     91                 cnt=0;
     92                 ///l~r,值为v。一开始数量是0,l从左到右,遇到左端点(排序),若右端点小于等于r,且v in [x,y],加1;遇到右端点(排序),若左端点大于等于l,且v in [x,y],减1。
     93                 s=vs[i];
     94                 t=vt[i];
     95 //                if (i==2 && j==5)
     96 //                {
     97 //                    printf("z");
     98 //                }
     99                 memset(add,0,sizeof(add));
    100                 for (l=i;l<=j;l++)
    101                 {
    102                     ///[i,l) (l,j]
    103                     ///interval[x,y] i<=x<=l l<=y<=j
    104                     while (s1[s].l==l)
    105                     {
    106                         if (s1[s].r<=j)
    107                             add[fan[s1[s].x]]++,add[fan[s1[s].y]+1]--;
    108                         s++;
    109                     }
    110                     while (s2[t].r==l-1)
    111                     {
    112                         if (s2[t].l>=i)
    113                             add[fan[s2[t].x]]--,add[fan[s2[t].y]+1]++;
    114                         t++;
    115                     }
    116                     cnt=0;
    117                     for (k=1;k<=g;k++)
    118                     {
    119                         cnt+=add[k];
    120                         value=temp[i][l-1][k]+temp[l+1][j][k]+cnt*v[k];
    121                         if (value>f[i][j][k])
    122                         {
    123                             f[i][j][k]=value;
    124                             pref[i][j][k]=l;
    125                         }
    126     //                    f[i][j][k]=max(f[i][j][k],temp[i][l][k]+temp[l+1][j][k]+cnt*v[k]);
    127                     }
    128             }
    129             temp[i][j][g]=f[i][j][g];
    130             pret[i][j][g]=g;
    131             for (k=g-1;k>=1;k--)
    132             {
    133                 if (temp[i][j][k+1]>f[i][j][k])
    134                 {
    135                     temp[i][j][k]=temp[i][j][k+1];
    136                     pret[i][j][k]=pret[i][j][k+1];
    137                 }
    138                 else
    139                 {
    140                     temp[i][j][k]=f[i][j][k];
    141                     pret[i][j][k]=k;
    142                 }
    143 //                temp[i][j][k]=max(temp[i][j][k+1],f[i][j][k]);
    144             }
    145         }
    146     sum=0;
    147     for (i=1;i<=g;i++)
    148         if (f[1][n][i]>sum)
    149             sum=f[1][n][i],j=i;
    150 //        sum=max(sum,f[1][n][i]);
    151     printf("%d
    ",sum);
    152     findarr(1,n,j);
    153     for (i=1;i<=n;i++)
    154         printf("%d%c",re[i],i==n?'
    ':' ');
    155     return 0;
    156 }
    157 /*
    158 5 1
    159 2 4 15 20
    160 
    161 5 2
    162 1 3 5 10
    163 4 5 2 4
    164 
    165 5 2
    166 1 5 10 15
    167 1 5 5 8
    168 
    169 5 2
    170 1 4 10 15
    171 2 3 5 8
    172 
    173 5 2
    174 1 4 5 8
    175 2 3 10 15
    176 
    177 5 4
    178 1 3 5 7
    179 2 4 7 8
    180 3 5 9 9
    181 1 4 4 5
    182 
    183 5 5
    184 1 2 3 5
    185 2 3 4 6
    186 3 4 2 5
    187 4 5 3 4
    188 1 5 7 8
    189 */

    超时代码:处理cnt不当

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <set>
      8 #include <map>
      9 #include <queue>
     10 #include <iostream>
     11 using namespace std;
     12 
     13 #define ll long long
     14 
     15 const int maxn=32;  ///pay attention
     16 const int maxm=4e3+10;  ///2*m
     17 const int inf=1e9;
     18 const double eps=1e-8;
     19 
     20 struct node1
     21 {
     22     int l,r,x,y;
     23     bool operator<(const node1 &b)
     24     {
     25         return l<b.l;
     26     }
     27 }s1[maxm];
     28 
     29 struct node2
     30 {
     31     int l,r,x,y;
     32     bool operator<(const node2 &b)
     33     {
     34         return r<b.r;
     35     }
     36 }s2[maxm];
     37 
     38 int f[maxn][maxn][maxm],temp[maxn][maxn][maxm],v[maxm],vv[maxm];
     39 int pref[maxn][maxn][maxm],pret[maxn][maxn][maxm],re[maxn],vs[maxm],vt[maxm];
     40 
     41 void findarr(int i,int j,int g)
     42 {
     43     re[pref[i][j][g]]=v[g];
     44     if (i<=pref[i][j][g]-1)
     45         findarr(i , pref[i][j][g]-1 , pret[i][ pref[i][j][g]-1 ][g]);
     46     if (pref[i][j][g]+1<=j)
     47         findarr(pref[i][j][g]+1 , j , pret[ pref[i][j][g]+1 ][j][g]);
     48 }
     49 
     50 int main()
     51 {
     52     int n,m,g=0,l,r,x,y,c,i,j,k,s,t,value,cnt,sum;
     53     scanf("%d%d",&n,&m);
     54     for (i=1;i<=m;i++)
     55     {
     56         scanf("%d%d%d%d",&l,&r,&x,&y);
     57         vv[i*2-1]=x,vv[i*2]=y;
     58         s1[i]={l,r,x,y};
     59         s2[i]={l,r,x,y};
     60     }
     61     sort(vv+1,vv+m*2+1);    ///m*2
     62     vv[0]=vv[1]-1;
     63     for (i=1;i<=m*2;i++)
     64         if (vv[i]!=vv[i-1])
     65             v[++g]=vv[i];
     66     sort(s1+1,s1+m+1);
     67     sort(s2+1,s2+m+1);
     68     s1[m+1].l=-1,s2[m+1].r=-1;
     69     j=1;
     70     for (i=1;i<=n;i++)  ///n
     71     {
     72         vs[i]=j;
     73         while (s1[j].l==i)
     74             j++;
     75     }
     76     j=1;
     77     for (i=1;i<=n;i++)
     78     {
     79         vt[i]=j;
     80         while (s2[j].r==i-1)
     81             j++;
     82     }
     83 
     84     memset(f,0xff,sizeof(f));///-1
     85     for (c=0;c<n;c++)
     86         for (i=1,j=c+i;j<=n;i++,j++)
     87         {
     88             for (k=1;k<=g;k++)
     89             {
     90                 cnt=0;
     91                 ///l~r,值为v。一开始数量是0,l从左到右,遇到左端点(排序),若右端点小于等于r,且v in [x,y],加1;遇到右端点(排序),若左端点大于等于l,且v in [x,y],减1。
     92                 s=vs[i];
     93                 t=vt[i];
     94 //                if (i==1 && j==4 && k==4)
     95 //                {
     96 //                    printf("z");
     97 //                }
     98                 for (l=i;l<=j;l++)
     99                 {
    100                     ///[i,l) (l,j]
    101                     ///interval[x,y] i<=x<=l l<=y<=j
    102                     while (s1[s].l==l)
    103                     {
    104                         if (s1[s].r<=j && s1[s].x<=v[k] && v[k]<=s1[s].y)
    105                             cnt++;
    106                         s++;
    107                     }
    108                     while (s2[t].r==l-1)
    109                     {
    110                         if (s2[t].l>=i && s2[t].x<=v[k] && v[k]<=s2[t].y)
    111                             cnt--;
    112                         t++;
    113                     }
    114                     value=temp[i][l-1][k]+temp[l+1][j][k]+cnt*v[k];
    115                     if (value>f[i][j][k])
    116                     {
    117                         f[i][j][k]=value;
    118                         pref[i][j][k]=l;
    119                     }
    120 //                    f[i][j][k]=max(f[i][j][k],temp[i][l][k]+temp[l+1][j][k]+cnt*v[k]);
    121                 }
    122             }
    123             temp[i][j][g]=f[i][j][g];
    124             pret[i][j][g]=g;
    125             for (k=g-1;k>=1;k--)
    126             {
    127                 if (temp[i][j][k+1]>f[i][j][k])
    128                 {
    129                     temp[i][j][k]=temp[i][j][k+1];
    130                     pret[i][j][k]=pret[i][j][k+1];
    131                 }
    132                 else
    133                 {
    134                     temp[i][j][k]=f[i][j][k];
    135                     pret[i][j][k]=k;
    136                 }
    137 //                temp[i][j][k]=max(temp[i][j][k+1],f[i][j][k]);
    138             }
    139         }
    140     sum=0;
    141     for (i=1;i<=g;i++)
    142         if (f[1][n][i]>sum)
    143             sum=f[1][n][i],j=i;
    144 //        sum=max(sum,f[1][n][i]);
    145     printf("%d
    ",sum);
    146     findarr(1,n,j);
    147     for (i=1;i<=n;i++)
    148         printf("%d%c",re[i],i==n?'
    ':' ');
    149     return 0;
    150 }
    151 /*
    152 5 1
    153 2 4 15 20
    154 
    155 5 2
    156 1 3 5 10
    157 4 5 2 4
    158 
    159 5 2
    160 1 5 10 15
    161 1 5 5 8
    162 
    163 5 2
    164 1 4 10 15
    165 2 3 5 8
    166 
    167 5 2
    168 1 4 5 8
    169 2 3 10 15
    170 
    171 5 4
    172 1 3 5 7
    173 2 4 7 8
    174 3 5 9 9
    175 1 4 4 5
    176 
    177 5 5
    178 1 2 3 5
    179 2 3 4 6
    180 3 4 2 5
    181 4 5 3 4
    182 1 5 7 8
    183 */

    去年

    FBeautiful Land

    01背包,size,value, Totsize, solve maxValue。

    空间太大,转变为以价值作为一维

    ( v为当前的总价值,f[v]为对应的最小使用空间\ f[v]=min(f[v],f[v-size_{i}]+cost_{i}) )

     

    O(sum(value)*n)

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <algorithm>
     7 #include <set>
     8 #include <map>
     9 #include <queue>
    10 #include <iostream>
    11 using namespace std;
    12 
    13 #define ll long long
    14 
    15 const int maxn=1e4+10;
    16 const int inf=1e9;
    17 const double eps=1e-8;
    18 
    19 int f[maxn];
    20 
    21 int main()
    22 {
    23     int t,n,m,i,j,a,b,tot;
    24     scanf("%d",&t);
    25     while (t--)
    26     {
    27         memset(f,0x3f,sizeof(f));
    28         scanf("%d%d",&n,&m);
    29         f[0]=0;
    30         tot=0;
    31         while (n--)
    32         {
    33             scanf("%d%d",&a,&b);
    34             tot+=b;
    35             for (j=tot;j>=b;j--)
    36                 f[j]=min(f[j],f[j-b]+a);
    37         }
    38         for (i=tot;i>=0;i--)
    39             if (f[i]<=m)
    40                 break;
    41         printf("%d
    ",i);
    42     }
    43     return 0;
    44 }
    45 /*
    46 
    47 */
  • 相关阅读:
    读书笔记:《HTML5开发手册》-- 现存元素的变化
    关于微信小程序,一些想法
    HTML5--details活学活用
    读书笔记:《HTML5开发手册》--figure、time、details、mark
    读书笔记:《HTML5开发手册》--HTML5新的结构元素
    微信小程序开源项目库汇总
    Debian安装fail2ban来防止扫描
    Debian更新软件源提示There is no public key available for the following key IDs的解决方法
    JavaBugCharSequence
    分析 《7吨碳九泄漏,40万泉港人在无声中消逝》虚假报道
  • 原文地址:https://www.cnblogs.com/cmyg/p/10705579.html
Copyright © 2011-2022 走看看