10月28日G、H、I題
阿新 • • 發佈:2020-10-28
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]); } } }