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]);
    }
  }
}
原文地址:https://www.cnblogs.com/hznudreamer/p/13892234.html