zoukankan      html  css  js  c++  java
  • 2017 ZSTU寒假排位赛 #3

      题目链接:https://vjudge.net/contest/147974#overview

      A题,费用流,不会。。跳过了。

      B题,给一个图,问至少添加几条边能成为强连通图。显然缩点,要使得成为一个scc,任意一个点都要至少一个入度和出度,而一条边可以提供一个入度和出度,因为答案为max(入度为0的点,出度为0的点)。如果要求最多能添加几条使得还不是scc,则参照:最多添加几条使得还不是scc。如果是无向图问至少添加几条使得是边双联通,则参照:至少添加几条使得边双联通

      C题,线段树区间合并,貌似暑假的时候写过类似的,但是忘记了。。代码如下:

     1 //#include <bits/stdc++.h>
     2 #include <stdio.h>
     3 #include <algorithm>
     4 #include <string.h>
     5 #define t_mid (l+r>>1)
     6 #define ls (o<<1)
     7 #define rs (o<<1|1)
     8 #define lson ls,l,t_mid
     9 #define rson rs,t_mid+1,r
    10 using namespace std;
    11 const int N = 100000 + 5;
    12 
    13 int a[N];
    14 // sub表示节点o的lcis的最长长度,l_val和r_val分别表示这个节点最左边和最右边的值分别是多少
    15 // l_sub表示这个节点从最左边开始的最长的lcis的长度,r_sub同
    16 int sub[N<<2],l_val[N<<2],r_val[N<<2],l_sub[N<<2],r_sub[N<<2];
    17 int T,n,q;
    18 void up(int o,int l,int r)
    19 {
    20     int len = r - l + 1;
    21     l_val[o] = l_val[ls], r_val[o] = r_val[rs]; // 更新l_val,r_val
    22     // 更新sub的值
    23     sub[o] = max(sub[ls], sub[rs]);
    24     if(r_val[ls] < l_val[rs]) sub[o] = max(sub[o], r_sub[ls]+l_sub[rs]);
    25 
    26     // 更新l_sub,r_sub
    27     l_sub[o] = l_sub[ls];
    28     if(l_sub[o] == len-len/2 && r_val[ls] < l_val[rs]) l_sub[o] += l_sub[rs];
    29 
    30     r_sub[o] = r_sub[rs];
    31     if(r_sub[o] == len/2 && r_val[ls] < l_val[rs]) r_sub[o] += r_sub[ls];
    32 }
    33 void build(int o,int l,int r)
    34 {
    35     if(l == r)
    36     {
    37         sub[o] = l_sub[o] = r_sub[o] = 1;
    38         l_val[o] = r_val[o] = a[l];
    39         return ;
    40     }
    41     build(lson);
    42     build(rson);
    43     up(o,l,r);
    44 }
    45 void update(int o,int l,int r,int pos,int x)
    46 {
    47     if(l == r)
    48     {
    49         l_val[o] = r_val[o] = x;
    50         return ;
    51     }
    52     if(pos <= t_mid) update(lson,pos,x);
    53     else update(rson,pos,x);
    54     up(o,l,r);
    55 }
    56 int query(int o,int l,int r,int ql,int qr)
    57 {
    58     if(l == ql && r == qr) return sub[o];
    59     int ans = 0;
    60     if(qr <= t_mid) ans = query(lson,ql,qr);
    61     else if(ql > t_mid) ans = query(rson,ql,qr);
    62     else
    63     {
    64         ans = max(query(lson,ql,t_mid), query(rson,t_mid+1,qr));
    65         // 注意下面一行的两个min
    66         if(r_val[ls] < l_val[rs]) ans = max(ans, min(r_sub[ls], t_mid-ql+1) + min(l_sub[rs], qr-t_mid));
    67     }
    68     return ans;
    69 }
    70 
    71 int main()
    72 {
    73     scanf("%d",&T);
    74     while(T--)
    75     {
    76         scanf("%d%d",&n,&q);
    77         for(int i=1;i<=n;i++) scanf("%d",a+i);
    78         build(1,1,n);
    79         while(q--)
    80         {
    81             char s[5];
    82             int x,y;
    83             scanf("%s%d%d",s,&x,&y);
    84             if(s[0] == 'U') update(1,1,n,x+1,y);
    85             else printf("%d
    ",query(1,1,n,x+1,y+1));
    86         }
    87     }
    88     return 0;
    89 }
    线段树区间合并

      D题,分组背包,每组中,先选择一个,然后该组中其他的有三个选择,不选,或者从之前一组中转移(也就是放弃了这组中第一个选的而选这组中的这个),或者从这组中的转移(这组中的第一个要选)。代码如下:

     1 #include <stdio.h>
     2 #include <algorithm>
     3 #include <string.h>
     4 #include <vector>
     5 #include <map>
     6 #include <set>
     7 #include <queue>
     8 #include <iostream>
     9 #include <stdlib.h>
    10 #include <string>
    11 #include <stack>
    12 using namespace std;
    13 const int inf = 0x3f3f3f3f;
    14 typedef long long ll;
    15 typedef pair<int,int> pii;
    16 const int N = 100 + 5;
    17 
    18 int n,m,k;
    19 vector<pii> v[15];
    20 int dp[15][15000+5];
    21 
    22 int main()
    23 {
    24     while(scanf("%d%d%d",&n,&m,&k) == 3)
    25     {
    26         for(int i=1;i<=k;i++) v[i].clear();
    27         for(int i=1;i<=n;i++)
    28         {
    29             int pos,mo,val;
    30             scanf("%d%d%d",&pos,&mo,&val);
    31             v[pos].push_back(pii(mo,val));
    32         }
    33         int sum = 0;
    34         int flag = 1;
    35         for(int i=1;i<=k;i++)
    36         {
    37             if(v[i].size() == 0)
    38             {
    39                 flag = 0;
    40                 break;
    41             }
    42             sort(v[i].begin(), v[i].end());
    43             sum += v[i][0].first;
    44         }
    45         if(sum > m || flag == 0)
    46         {
    47             printf("Impossible
    ");
    48             continue;
    49         }
    50         memset(dp,0,sizeof dp);
    51         for(int i=1;i<=k;i++)
    52         {
    53             for(int j=0;j<v[i].size();j++)
    54             {
    55                 int w = v[i][j].first, val = v[i][j].second;
    56                 for(int mask=m;mask>=w;mask--)
    57                 {
    58                     if(j == 0) dp[i][mask] = dp[i-1][mask-w] + val;
    59                     else dp[i][mask] = max({dp[i][mask], dp[i-1][mask-w]+val, dp[i][mask-w]+val});
    60                 }
    61             }
    62         }
    63         printf("%d
    ",dp[k][m]);
    64     }
    65 }
    分组背包

      E题,直接暴力枚举即可。完全背包也行。第一次wa是因为认为贪心先拿最小的最优,其实不然。例如:53--10,11,23。显然11的拿3个再拿10的两个比较好。

      

  • 相关阅读:
    OGG实时同步Oracle数据到Kafka实施文档(供flink流式计算)
    Oracle exp导出加where指定条件
    oracle merge into的用法
    Oracle列转行函数LISTAGG() WITHIN GROUP ()的使用方法
    sql怎样查一个存储过程被谁调用
    Oracle JOB间隔时间详解
    如何在ORACLE下创建JOB,并且赋予ID号?
    DOS下查看进程对应的文件路径
    查询系统中运行的JOB
    plsql中书写一个简单的存储过程
  • 原文地址:https://www.cnblogs.com/zzyDS/p/6305426.html
Copyright © 2011-2022 走看看