1. 程式人生 > 實用技巧 >10月28日G、H、I題

10月28日G、H、I題

Train Problem I

題意:給出元素入棧順序和出棧順序,問該入棧順序的條件下是否可能得到該出棧順序。

分析:模擬。每次入棧後貪心匹配滿足條件的出棧元素,最後判斷棧是否為空。

const int N = 1e5+10;
char s1[N], s2[N];
int ans[N];
stack<char> st;
void run() {
  int n;
  while (~scanf("%lld%s%s",&n,s1+1,s2+1)) {
    while (!st.empty()) st.pop();
    int i = 0, j = 1, cnt = 0;
    while (i++, i <= n) {
      st.push(s1[i]), ans[++cnt] = 1;
      while (!st.empty() && st.top() == s2[j]) st.pop(), j++, ans[++cnt] = 0;
    }
    if (!st.empty()) puts("No.");      
    else {
      puts("Yes.");
      rep(i,1,cnt) puts(ans[i] ? "in" : "out");
    }
    puts("FINISH");
  }
}

Feel Good

題意:求max{子段和*該子段最小值}。

分析:單調棧。單調棧求最大矩形面積模板的寬改為子段和來更新答案即可。

const int N = 1e5+10;
int a[N], sum[N], st[N];
void run() {
  int n = rd(), tail = 1, ans = 0, l = 1, r = 1;
  rep(i,1,n) a[i] = rd(), sum[i] = sum[i-1] + a[i];
  rep(i,1,n) {
    bool flg = false;
    int tmp;
    while (tail > 1 && a[i] < a[st[tail-1]]) {
      flg = true;
      tmp = st[tail-1];
      if ((sum[i-1] - sum[st[tail-1]-1]) * a[st[tail-1]] > ans) {
        ans = (sum[i-1] - sum[st[tail-1]-1]) * a[st[tail-1]];
        r = i-1, l = st[tail-1];
      }
      tail--;
    }
    if (flg) {
      st[tail++] = tmp;
      a[tmp] = a[i];
    } else {
      st[tail++] = i;
    }
  }
  while (tail > 1) {
    if ((sum[n] - sum[st[tail-1]-1]) * a[st[tail-1]] > ans) {
        ans = (sum[n] - sum[st[tail-1]-1]) * a[st[tail-1]];
        r = n, l = st[tail-1];
      }
    tail--;
  }
  pnt(ans);
  put(l), pnt(r);
}

Vessels

題意:\(n\)個船從上向下疊,第\(i\)個船容積\(a[i]\)

2個操作:

1.往下標\(p[i]\)的船注入\(x[i]\)的水,若已滿則向下溢位。

2.查詢下標為\(k[i]\)的船裡有多少水。

分析:模擬。維護當前船往下還未注滿水的第一艘船的下標。維護方法可以暴力優化或者並查集。

const int N = 2e5+10;
int c[N], a[N], fa[N];
int find(int x) {return x ^ fa[x] ? fa[x] = find(fa[x]) : x;}
void merge(int x, int y) {
  x = find(x), y = find(y);
  if (x != y) fa[x] = y;
}
void run() {
  int n = rd();
  rep(i,1,n) c[i] = rd();
  rep(i,1,n+1) fa[i] = i;
  int q = rd();
  while (q--) {
    if (rd() == 1) {
      int p = rd(), x = rd();
      while (x) {
        p = find(p);
        if (p > n) break;
        if (a[p] + x >= c[p]) {
          x -= c[p] - a[p];
          a[p] = c[p];
          merge(p, p+1);
        } else {
          a[p] += x;
          break;
        }
      }
    } else {
      int k = rd();
      pnt(a[k]);
    }
  }
}