CF558E A Simple Task
阿新 • • 發佈:2018-08-05
main private 範圍 字符串排序 prev turn ace mem amp
題目大意
給定一個長度不超過10^5的字符串(小寫英文字母),和不超過5000個操作。每個操作 L R K 表示給區間[L,R]的字符串排序,K=1為升序,K=0為降序。最後輸出最終的字符串。
題解
我們做過luogu2828,那裏我們無法對一段數字序列進行具體排序,那麽這道題我們就要考慮其獨有的特點。字母只有26個!所以我們對每個字母維護一個key值為下標,值為在下標範圍內該字母出現次數的權值線段樹即可,修改查詢都很方便。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAX_N = 100010, MAX_ALPHA = 30; int N; int OrgData[MAX_N]; int ValPosCnt[MAX_ALPHA][MAX_N]; struct RangeTree { private: static const int MAX_NODE = MAX_N * 4; int Sum[MAX_NODE], Cover[MAX_NODE]; void PushDown(int cur, int l, int r) { if(Cover[cur] != -1) { Cover[cur * 2] = Cover[cur * 2 + 1] = Cover[cur]; int mid = (l + r) / 2; Sum[cur * 2] = (mid - l + 1) * Cover[cur]; Sum[cur * 2 + 1] = (r - mid) * Cover[cur]; Cover[cur] = -1; } } void PullUp(int cur) { Sum[cur] = Sum[cur * 2] + Sum[cur * 2 + 1]; } void Init(int cur, int l, int r, int *a) { if(l == r) { Sum[cur] = a[l]; return; } int mid = (l + r) / 2; Init(cur * 2, l, mid, a); Init(cur * 2 + 1, mid + 1, r, a); PullUp(cur); } int Query_Update(int cur, int curL, int curR, int askL, int askR, int cover) { if(askL <= curL && curR <= askR) { int ans = Sum[cur]; Sum[cur] = (curR - curL + 1) * cover; Cover[cur] = cover; return ans; } PushDown(cur, curL, curR); int mid = (curL + curR) / 2, ans = 0; if(askL <= mid) ans += Query_Update(cur * 2, curL, mid, askL, askR, cover); if (askR > mid) ans += Query_Update(cur * 2 + 1, mid + 1, curR, askL, askR, cover); PullUp(cur); return ans; } void OutPut(int cur, int l, int r, int *a, int val) { if(Sum[cur] == r - l + 1) { for (int i = l; i <= r; i++) a[i] = val; return; } PushDown(cur, l, r); int mid = (l + r) / 2; if(Sum[cur * 2]) OutPut(cur * 2, l, mid, a, val); if (Sum[cur * 2 + 1]) OutPut(cur * 2 + 1, mid + 1, r, a, val); } public: RangeTree() { memset(Cover, -1, sizeof(Cover)); } void Init(int *a) { Init(1, 1, N, a); } int Query_Update(int l, int r, int cover) { return Query_Update(1, 1, N, l, r, cover); } void OutPut(int *a, int val) { OutPut(1, 1, N, a, val); } }g[MAX_ALPHA]; int main() { int opCnt; scanf("%d%d\n", &N, &opCnt); for (int i = 1; i <= N; i++) { char c; scanf("%c", &c); OrgData[i] = c - ‘a‘ + 1; } for (int i = 1; i <= N; i++) ValPosCnt[OrgData[i]][i] += 1; for (int i = 1; i <= 26; i++) g[i].Init(ValPosCnt[i]); while(opCnt--) { int l, r, op; scanf("%d%d%d", &l, &r, &op); switch(op) { int prevR, prevL, num; case 1: prevR = l - 1; for (int i = 1; i <= 26; i++) { num = g[i].Query_Update(l, r, 0); if (num) { g[i].Query_Update(prevR + 1, prevR + num, 1); prevR = prevR + num; } } break; case 0: prevL = r + 1; for (int i = 1; i <= 26; i++) { num = g[i].Query_Update(l, r, 0); if (num) { g[i].Query_Update(prevL - num, prevL - 1, 1); prevL = prevL - num; } } break; } } static int ans[MAX_N]; memset(ans, 0, sizeof(ans)); for (int i = 1; i <= 26; i++) g[i].OutPut(ans, i); for (int i = 1; i <= N; i++) printf("%c", ans[i] + ‘a‘ - 1); printf("\n"); return 0; }
CF558E A Simple Task