暴力+树状数组维护 Codeforces Round #378 (Div. 2) C

题目大意:给你一个长度为n的数组a,然后数值大的可以合并数值小的,且合并了以后该数组的长度-1.给你一个长度为k目标数组b,问,是否可以从a数组变到b数组,是就yes并且输出步骤。否就输出no

思路:因为合并的时候要删除某一个数字,很容易想到用树状数组来维护。然后分析一下就可以得到b中第i个数,一定是由a的某一段区间得到的。我们只要找到这一段区间就行啦。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #pragma comment(linker,"/STACK:102400000,102400000")
  4 #define LL long long
  5 #define ALL(a) a.begin(), a.end()
  6 #define pb push_back
  7 #define mk make_pair
  8 #define fi first
  9 #define se second
 10 #define haha printf("haha
")
 11 const int maxn = 500 + 5;
 12 int n, k;
 13 int a[maxn], b[maxn];
 14 int tree[maxn];
 15 vector<pair<int, int> > v;
 16 
 17 void update(int x, int val = 1){
 18     for (int i = x; i <= maxn - 5; i += i & -i)
 19         tree[i] += val;
 20 }
 21 
 22 int sum(int pos){
 23     int ans = 0;
 24     for (int i = pos - 1; i > 0; i -= i & -i){
 25         ans += tree[i];
 26     }
 27     return ans;
 28 }
 29 
 30 vector<pair<int, char> > ans;
 31 
 32 void eat(int pos, int lb, int rb){
 33     if (pos == rb || a[pos] > a[pos - 1]){
 34         for (int i = pos - 1; i >= lb; i--){
 35             int reduce = sum(pos);
 36             ans.push_back(mk(pos - reduce, 'L'));
 37             update(i);
 38         }
 39         for (int i = pos + 1; i <= rb; i++){
 40             int reduce = sum(pos);
 41             ans.push_back(mk(pos - reduce, 'R'));
 42             update(i);
 43         }
 44     }
 45     else {
 46         for (int i = pos + 1; i <= rb; i++){
 47             int reduce = sum(pos);
 48             ans.push_back(mk(pos - reduce, 'R'));
 49             update(i);
 50         }
 51         for (int i = pos - 1; i >= lb; i--){
 52             int reduce = sum(pos);
 53             ans.push_back(mk(pos - reduce, 'L'));
 54             update(i);
 55         }
 56     }
 57 }
 58 
 59 bool solve(){
 60     a[n + 1] = 0x3f3f3f3f;
 61     int lb = 1;
 62     for (int i = 1; i <= k; i++){
 63         int val = b[i];
 64         for (int j = lb; j <= n; j++){
 65             if (val == a[j]){
 66                 v.push_back(mk(lb, j));
 67                 lb = j + 1;
 68                 break;
 69             }
 70             else if (val > a[j]) val -= a[j];
 71             else return false;
 72         }
 73         if (lb > n) break;
 74     }
 75     if (v.size() != k) return false;
 76     for (int i = 0; i < v.size(); i++){
 77         int lb = v[i].fi, rb = v[i].se;
 78         int val = a[lb];
 79         bool flag = (rb == lb ? true : false);
 80         for (int j = lb + 1; j <= rb; j++){
 81             if (val != a[j]) {
 82                 flag = true;
 83                 break;
 84             }
 85         }
 86         if (!flag) return false;
 87     }
 88     for (int i = 0; i < v.size(); i++){
 89         int lb = v[i].fi, rb = v[i].se;
 90         if (lb == rb) continue;
 91         int maxval = a[lb], pos = lb;
 92         for (int j = lb + 1; j <= rb; j++){
 93             if (maxval < a[j]) {maxval = a[j]; pos = j;}
 94             else if (maxval == a[j] && a[j - 1] < a[j]) pos = j;
 95             else if (maxval == a[j] && a[j + 1] < a[j] && j < rb) pos = j;
 96         }
 97         eat(pos, lb, rb);
 98     }
 99     return true;
100 }
101 
102 int main(){
103     scanf("%d", &n);
104     int sum = 0;
105     for (int i = 1; i <= n; i++) scanf("%d", a + i), sum += a[i];
106     scanf("%d", &k);
107     for (int i = 1; i <= k; i++) scanf("%d", b + i), sum -= b[i];
108     if (sum != 0) printf("NO
");
109     else {
110         bool flag = solve();
111         if (!flag) printf("NO
");
112         else {
113             printf("YES
");
114             for (int i = 0; i < ans.size(); i++){
115                 pair<int, char> p = ans[i];
116                 printf("%d %c
", p.fi, p.se);
117             }
118         }
119     }
120     return 0;
121 }
View Code
原文地址:https://www.cnblogs.com/heimao5027/p/6020955.html