zoukankan      html  css  js  c++  java
  • codeforce 380(div.2)

    A B 略

    C:二分,贪心

    设d(i, v)为 剩余油量为v时,车开距离i 所需要的最小时间,使用线性规划不难算出:

    if v < i return INF; //无法到达
    if v > 2*i return i;  
    if  i <= v <= 2*i return LL(3)*i - v;

    那么一辆车开到终点的最短时间等于 ∑d(g[i]-g[i-1], v)
    这样只需要二分能开到终点的最小油量,取其中价格最低的即是答案
    代码如下:
     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4 
     5 using namespace std;
     6 #define INF 9999999999LL
     7 const int maxn = 2e5 + 10;
     8 int n, k, s, t;
     9 typedef long long LL ;
    10 LL cal(LL i, LL v) {
    11     if(v < i) return INF;
    12     if(v > 2*i) return i;
    13     return LL(3)*i - v;
    14 }
    15 int c[maxn], v[maxn];
    16 int g[maxn];
    17 bool judge(LL v) {
    18     LL sum = 0;
    19     for(int i = 1; i <= k+1; i++) {
    20         sum += cal(g[i]-g[i-1], v);
    21         if(sum > t) return false;
    22     }
    23     return true;
    24 }
    25 int main() {
    26     scanf("%d%d%d%d", &n, &k, &s, &t);
    27     for(int i = 0; i < n; i++) {
    28         scanf("%d%d", &c[i], &v[i]);
    29     }
    30     g[0] = 0;
    31     for(int i = 1; i <= k; i++) {
    32         scanf("%d", &g[i]);    
    33     }
    34     g[k+1] = s;
    35     sort(g, g+k+2);
    36     LL L = 0, R = INF;
    37     while(L < R) {
    38         LL M = L + (R-L)/2;
    39         if(judge(M)) R = M;
    40         else L = M+1;
    41     }
    42 //    printf("R = %d
    ", R);
    43     int ans = 1000000010;
    44     for(int i = 0; i < n; i++) {
    45         if(v[i] >= R) ans = min(ans, c[i]);        
    46     }
    47     if(ans < 1000000010) printf("%d
    ", ans);
    48     else puts("-1");
    49 }

    D: 一道堪比A、B的水题,按顺序输出剩下的可以放船的位置直到不能装下所有船为止

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <utility>
     4 #include <vector>
     5 using namespace std;
     6 const int maxn = 2e5 + 10;
     7 
     8 int n, a, b, k;
     9 char s[maxn];
    10 vector<pair<int, int> > vec;
    11 vector<int> ans;
    12 int main() {
    13     scanf("%d%d%d%d%s", &n, &a, &b, &k, s);
    14     int cnt = 0;
    15     for(int i = 0; i < n; ) {
    16         int j = i+1;
    17         if(s[i] == '0') {
    18             while(s[j] == '0') j++;
    19             if(j-i >= b){
    20                 vec.push_back(make_pair(i, j));
    21                 cnt += (j-i)/b;
    22             }
    23         }
    24         i = j;
    25     }
    26     int k = cnt - a + 1;
    27     printf("%d
    ", k);
    28     for(int i = 0;k && i < vec.size(); i++) {
    29         int l = vec[i].first;
    30         int r = vec[i].second;
    31         int j = l + b - 1;
    32         while(k && j < r) {
    33             ans.push_back(j);
    34             j += b;
    35             k--;
    36         }
    37     }
    38     printf("%d", ans[0]+1);
    39     for(int i = 1; i < ans.size(); i++) printf(" %d", ans[i]+1);
    40     printf("
    ");
    41 }

    E:贪心,数状数组维护前缀和

    分析题意我们可以发现,由于一个下级只能有一个直接上级,一个上级可以有多个直接从属,比如

    5 1

    0 1 1 1 1 

    最小出错数为0;

    我们以num[i+1]表示有i个上级的人数 (i+1是为了方便写树状数组),用c[i+1] 来记录上级数为i的情况是否缺少,

    c[i+1] = 0 表示 有i个上级的人数不为0,c[i+1] = 1 有i个上级的人数为0,即没有上级数为i的人

    用数状数组维护 上级数小于 i 的情况中缺少的总个数。

    比如 0 1 1 3 5, 上级数为i之前缺一个上级数为2的情况 ,所以get(3) = 1, 上级数为5之前缺少2 和 4 的情况, 所以get(5) = 2;

    设错误人数为cnt,初始为0,用一个队列维护最大位置前缺少的位置

    然后从上级数最多的情况开始考虑,

      考虑上级数 为 i时,

        if get(i) = 0   , print cnt   //这时所有的上级数已经连续,  此时cnt就是答案

        else {

          将上级数为i的人一个一个依次填充到之前缺失的位置(相应上级数值),直到num[i] = 0 或者 缺失的位置被填满  

          注意:比最大上级数还要大的位置不需要填,容易出错   

        }

           

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <queue>
     4 using namespace std;
     5 const int maxn = 2e5 + 10;
     6 
     7 int n, s;
     8 int a[maxn];
     9 int c[maxn];
    10 int d[maxn];
    11 int num[maxn];
    12 void add(int x, int v) {
    13     while(x < maxn) {
    14         d[x] += v;
    15         x += x&-x;
    16     }
    17 }
    18 int get(int x) {
    19     int ans = 0;
    20     while(x) {
    21         ans += d[x];
    22         x -= x&-x;
    23     }
    24     return ans;
    25 }
    26 queue<int> Q;
    27 int main(){
    28     scanf("%d%d", &n, &s);
    29     int cnt = 0;
    30     int start = 0;
    31     for(int i = 1; i <= n; i++) c[i] = 1;
    32     for(int i = 1; i <= n; i++) {
    33         scanf("%d", &a[i]);
    34         if(i == s && a[i] != 0){
    35             cnt++;    
    36         } else if(i != s && a[i] == 0) {
    37             cnt++;
    38         } else {
    39             num[a[i]+1]++;
    40             c[a[i]+1] = 0;    
    41             start = max(start,a[i]+1);
    42         }
    43     }
    44     for(int i = 1; i <= start; i++) if(c[i] == 1) {
    45         Q.push(i);    
    46     }
    47     int k = cnt;
    48     while(k && !Q.empty()) {
    49         int i = Q.front(); 
    50         Q.pop();
    51         k--;
    52         c[i] = 0;
    53         num[i]++;
    54     }
    55     for(int i = 1; i <= n; i++) add(i, c[i]);
    56     for(int i = start; i > 0; i--) {
    57         int temp = get(i);
    58         if(temp) {
    59             int &k = num[i];
    60             while(k && !Q.empty()) {
    61                 int u = Q.front(); 
    62                 Q.pop();
    63                 if(u >= i) break;
    64                 k--;
    65                 c[u] = 0;
    66                 add(u, -1);
    67                 num[u]++;
    68                 cnt++;
    69             }    
    70         }
    71         else {
    72             break;
    73         }
    74     }
    75     printf("%d
    ", cnt);
    76 }

    F: 容易想到DP, 设d(i, j, k)为当前 Igor 先手时的状态,然后记忆化搜索,但是很不幸这样会爆内存 - -||

    由于k的值不断增大,经简单计算k最大为64,并且Igor拿去的数量与zhenya拿去的数量之差不超过 64,  i <= n/2 ,

    这样我们可以设 d(i, r, k) ,r 为 zhenya比Igor多拿的数量+70(差值可能为负)

    maxi = 2100, maxr = 140,  maxk = 70

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <vector>
     5 
     6 using namespace std;
     7 const int maxn = 4001;
     8 #define INF 1000000007
     9 #define S(i, j) (sum[j] - sum[i-1])
    10 
    11 int sum[maxn];
    12 int n;
    13 
    14 int d[2100][140][70];
    15 int vis[2100][140][70];
    16 int dp(int i, int r, int k) {
    17     int j = n - r - (i-1) + 70;
    18     //printf("%d %d %d
    ", i, j, k);
    19     if(i + k - 1> j) return 0;
    20     if(vis[i][r][k]) return d[i][r][k];
    21     vis[i][r][k] = 1;
    22     int &ans = d[i][r][k];
    23     ans = -INF;    
    24     int temp = S(i, i+k-1);
    25     int temp2;
    26     if(j-k+1 > i+k-1) {
    27         temp2 = -S(j-k+1, j) + dp(i+k, n-(j-k)-(i+k-1)+70, k);
    28         if(j-k > i+k-1) {
    29             temp2 = min(temp2, -S(j-k, j) + dp(i+k, n-(j-k-1)-(i+k-1)+70, k+1));
    30             ans = max(ans, temp+temp2);
    31         }
    32         else ans = max(ans, temp+temp2);
    33     }
    34     else ans = max(ans, temp);
    35     
    36     if(i + k > j) return ans;
    37     temp = S(i, i+k);
    38     if(j-k > i+k) {
    39         temp2 = - S(j-k, j) + dp(i+k+1, n-(j-k-1)-(i+k+1-1)+70, k+1);
    40         if(j-k-1 > i+k) {
    41             temp2 = min(temp2, -S(j-k-1, j) + dp(i+k+1, n-(j-k-2)-(i+k+1-1)+70, k+2));
    42             ans = max(ans, temp+temp2);
    43         }
    44         else ans = max(ans, temp+temp2);
    45     }
    46     else ans = max(ans, temp);
    47     
    48     return ans;
    49 }
    50 int main() {
    51     
    52     scanf("%d", &n);
    53     sum[0] = 0;
    54     for(int i = 1; i <= n; i++) {
    55         int a;
    56         scanf("%d", &a);
    57         sum[i] = sum[i-1] + a;
    58     }
    59     int ans;
    60     ans = dp(1, 70, 1);
    61     printf("%d
    ", ans);
    62     return 0;
    63 }
  • 相关阅读:
    Linux中创建Daemon进程的三种方法【转】
    Linux 内核定时器使用 二 高精度定时器 hrtimer 的用例【转】
    使用 Qemu 虚拟 ARM64 平台演示 kdump 崩溃转存【转】
    自旋锁 spin_lock、 spin_lock_irq 以及 spin_lock_irqsave 的区别【转】
    Linux中的spinlock机制[四]
    Linux中的虚拟内存机制和内存映射【转】
    那些情况该使用它们spin_lock到spin_lock_irqsave【转】
    Linux内核中的软中断、tasklet和工作队列详解【转】
    Linux 读写memory操作,devmem直接访问物理内存地址【转】
    Linux性能之DVFS/cpufreq【转】
  • 原文地址:https://www.cnblogs.com/Kiraa/p/6097052.html
Copyright © 2011-2022 走看看