• bzoj 3704 昊昊的机油之GRST


    题目传送门

      传送门

    题目大意

      给定一个数组$a$和数组$b$,每次操作可以选择$a$的一个子区间将其中的数在模4意义下加1,问把$a$变成$b$的最少操作次数。

      首先求$b - a$,再差分,令这个数组为$c$。

      那么操作的次数是这个数组$c$中正数的和。

      现在可以做的是选择一个地方+4,它后面的某个地方-4。

      考虑什么时候可以使得当前的答案减少。

    • 在$-3$处$+4$,在$3$处$-4$,答案减少2
    • 在$-3$处$+4$,在$2$处$-4$,答案减少1
    • 在$-2$处$+4$,在$3$处$-4$,答案减少1

      首先我们将尽量靠后的$-3$和$3$匹配,然后将对它操作。

      这个用一个栈就能做。

      剩下就贪心一下就好了。注意当$-3$和$2$操作时会多出$-2$。

    Code

      1 /**
      2  * bzoj
      3  * Problem#3704
      4  * Accepted
      5  * Time: 1400ms
      6  * Memory: 128316k
      7  */
      8 #include <iostream>
      9 #include <cstdlib>
     10 #include <cstdio>
     11 #include <queue>
     12 #include <stack>
     13 using namespace std;
     14 typedef bool boolean;
     15  
     16 typedef class Input {
     17     protected:
     18         const static int limit = 65536;
     19         FILE* file; 
     20  
     21         int ss, st;
     22         char buf[limit];
     23     public:
     24          
     25         Input():file(NULL)  {   };
     26         Input(FILE* file):file(file) {  }
     27  
     28         void open(FILE *file) {
     29             this->file = file;
     30         }
     31  
     32         void open(const char* filename) {
     33             file = fopen(filename, "r");
     34         }
     35  
     36         char pick() {
     37             if (ss == st)
     38                 st = fread(buf, 1, limit, file), ss = 0;//, cerr << "str: " << buf << "ed " << st << endl;
     39             return buf[ss++];
     40         }
     41 }Input;
     42  
     43 #define digit(_x) ((_x) >= '0' && (_x) <= '9')
     44  
     45 Input& operator >> (Input& in, unsigned& u) {
     46     char x;
     47     while (~(x = in.pick()) && !digit(x));
     48     for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
     49     return in;
     50 }
     51  
     52 Input& operator >> (Input& in, unsigned long long& u) {
     53     char x;
     54     while (~(x = in.pick()) && !digit(x));
     55     for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
     56     return in;
     57 }
     58  
     59 Input& operator >> (Input& in, int& u) {
     60     char x;
     61     while (~(x = in.pick()) && !digit(x) && x != '-');
     62     int aflag = ((x == '-') ? (x = in.pick(), -1) : (1));
     63     for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
     64     u *= aflag;
     65     return in;
     66 }
     67  
     68 Input& operator >> (Input& in, long long& u) {
     69     char x;
     70     while (~(x = in.pick()) && !digit(x) && x != '-');
     71     int aflag = ((x == '-') ? (x = in.pick(), -1) : (1));
     72     for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
     73     u *= aflag;
     74     return in;
     75 }
     76  
     77 Input& operator >> (Input& in, char* str) {
     78     for (char x; ~(x = in.pick()) && x != '
    ' && x != ' '; *(str++) = x);
     79     return in;
     80 }
     81  
     82 Input in (stdin);
     83  
     84 template <typename T>
     85 void pfill(T* pst, const T* ped, T val) {
     86     for ( ; pst != ped; *(pst++) = val);
     87 }
     88  
     89 int n;
     90 int *a, *b, *c;
     91 boolean *used;
     92  
     93 inline void init() {
     94     in >> n;
     95     a = new int[(n + 1)];
     96     b = new int[(n + 1)];
     97     c = new int[(n + 1)];
     98     for (int i = 1; i <= n; i++) {
     99         in >> a[i];
    100     }
    101     for (int i = 1; i <= n; i++) {
    102         in >> b[i];
    103         c[i] = (b[i] - a[i] + 4) % 4; 
    104     }
    105 }
    106  
    107 stack<int> sta;
    108 inline void solve() {
    109     int ans = 0;
    110     for (int i = n; i > 1; i--)
    111         c[i] = c[i] - c[i - 1];
    112     used = new boolean[(n + 1)];
    113     pfill(used, used + n + 1, false);
    114     for (int i = 1; i <= n; i++)
    115         if (c[i] > 0)
    116             ans += c[i];
    117     for (int i = 1, y; i <= n; i++)
    118         if (c[i] == -3)
    119             sta.push(i);
    120         else if (c[i] == 3 && !sta.empty()) {
    121             y = sta.top();
    122             sta.pop();
    123             used[y] = used[i] = true;
    124             ans -= 2;
    125         }
    126      
    127     int have_2 = 0, have_3 = 0;
    128     for (int i = 1; i <= n; i++) {
    129         if (used[i])
    130             continue;
    131         switch (c[i]) {
    132             case 3:
    133                 if (have_3)
    134                     have_3--, ans--;
    135                 else if (have_2)
    136                     have_2--, ans--;    
    137                 break;
    138             case 2:
    139                 if (have_3)
    140                     have_3--, have_2++, ans--;
    141                 break;
    142             case -2:
    143                 have_2++;
    144                 break;
    145             case -3:
    146                 have_3++;
    147                 break;
    148         }
    149     }
    150     printf("%d
    ", ans);
    151 }
    152  
    153 int main() {
    154     init();
    155     solve();
    156     return 0;
    157 }
  • 相关阅读:
    Ubuntu系统Anaconda安装Pytorch,教你如何优雅的安装环境(1-5)
    优雅的装系统------安装MacOS 10.13.5系统教程
    关闭Ubuntu系统更新方法
    毫秒钟搞定anaconda环境使用清华镜像安装OpenCV,教你如何优雅的安装环境(1-4)
    Ubuntu16.04安装Anaconda3并配置国内镜像,教你优雅的安装环境(1-3)
    Anaconda常用命令
    Ubuntu16.04安装CUDA10.2+cuDNN7.6.5(福利区),教你如何优雅的安装环境(1-2)
    Ubuntu16.04安装NVIDIA驱动,教你如何优雅的安装环境(1-1)
    简述 QPS、TPS、并发用户数、吞吐量关系
    Springboot验证注解@vaild的使用
  • 原文地址:https://www.cnblogs.com/yyf0309/p/10175518.html
Copyright © 2020-2023  润新知