2019 Multi-University Training Contest 2
1002.Beauty Of Unimodal Sequence
题意:给定一个数组,找出其最长,且字典序最小/大的单峰序列。
我的思路:对于字典序最小,收先需处理$i-n$的包括i数字的最长下降和最长单峰子序列,再从前往后贪心选数且判断该选择是否合法。最长下降可以用以前经典方法,最长单峰可以用线段树维护$l$长单峰序列最后一个值。字典序最大直接反转数组再求一遍即可。
代码:
1 #include <bits/stdc++.h> 2 #define lson l,mid,rt<<1 3 #define rson mid+1,r,rt<<1|1 4 using namespace std; 5 6 const int N = 3e5 + 5; 7 8 int nod[N<<2]; 9 void build(int l, int r, int rt) { 10 nod[rt] = 0; 11 if (l == r) { 12 return ; 13 } 14 int mid = (l+r)>>1; 15 build(lson); 16 build(rson); 17 } 18 void update(int p, int x, int l, int r, int rt) { 19 if (l == r) { 20 if (nod[rt] < x) { 21 nod[rt] = x; 22 } 23 return ; 24 } 25 int mid = (l+r)>>1; 26 if (p <= mid) update(p, x, lson); 27 else update(p, x, rson); 28 nod[rt] = max(nod[rt<<1], nod[rt<<1|1]); 29 } 30 int query(int x, int l, int r, int rt) { 31 if (l == r) { 32 return l; 33 } 34 int mid = (l+r)>>1; 35 if (nod[rt<<1|1] > x) return query(x, rson); 36 else return query(x, lson); 37 } 38 39 int a[N]; 40 int c[N]; 41 int suf1[N], suf2[N]; 42 int ans[N]; 43 44 void solve(int n, int f) 45 { 46 build(1, n, 1); 47 int l1, l2; 48 int ansl = 0; 49 l1 = l2 = c[0] = 0; 50 for (int i = n - 1; i >= 0; -- i) { 51 int k = lower_bound(c, c + l1 + 1, a[i]) - c; 52 c[k] = a[i]; 53 suf1[i] = k; 54 l1 = max(k, l1); 55 int ps = 1; 56 if (nod[1] > a[i]) { 57 ps = query(a[i], 1, n, 1) + 1; 58 } 59 update(ps, a[i], 1, n, 1); 60 update(l1, a[i], 1, n, 1); 61 suf2[i] = max(ps, l1); 62 ansl = max(ansl, suf2[i]); 63 //cout << i << " " << suf1[i] << " " << suf2[i] << endl; 64 } 65 int F = 0; //f = 0 ins : 1 des 66 int p = 0; 67 for (int i = 0; i < n; ++ i) { 68 if (p == 0) { 69 if (suf2[i] == ansl) 70 ans[p ++] = i; 71 continue; 72 } 73 if (!F && a[i] > a[ans[p - 1]] && p + suf2[i] == ansl) { 74 ans[p ++] = i; 75 continue; 76 } 77 if (a[i] < a[ans[p - 1]] && p + suf1[i] == ansl) { 78 ans[p ++] = i; F = 1; 79 continue; 80 } 81 } 82 for (int i = 0; i < p; ++ i) { 83 int pt = n - ans[p - i - 1]; 84 if (f) pt = ans[i] + 1; 85 printf("%d%c", pt, i == p-1 ? '\n' : ' '); 86 } 87 } 88 89 int main() 90 { 91 int n; 92 while (scanf("%d", &n) != EOF) { 93 for (int i = 0; i < n; ++ i) { 94 scanf("%d", a + i); 95 } 96 solve(n, 1); 97 for (int i = 0; i < n / 2; ++ i) { 98 swap(a[i], a[n - i - 1]); 99 } 100 solve(n, 0); 101 } 102 return 0; 103 }
1012.Longest Subarray
题意:给定一个数组,找出最长连续子序列使得每种数出现次数均大于$K$。
我的思路:固定右端点,按照数字种类维护每种数字合法左端点,对这些位置$+1$,查询时找出最左边等于$C$的位置即可。
代码:
1 #include <bits/stdc++.h> 2 #define lson l,mid,rt<<1 3 #define rson mid+1,r,rt<<1|1 4 using namespace std; 5 6 namespace fastIO { 7 //fread -> read 8 const int BUF_SIZE = 1000000; 9 bool IOerror = 0; 10 inline char nc() { 11 //FILE* fp=fopen("123.txt","r"); 12 static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE; 13 if(p1 == pend) { 14 p1 = buf; 15 pend = buf + fread(buf, 1, BUF_SIZE, stdin); 16 if(pend == p1) { 17 IOerror = 1; 18 return -1; 19 } 20 } 21 return *p1++; 22 } 23 24 //输入挂,EOF返回0,有输入返回1. 25 template <class T> 26 inline bool read(T &ret) { 27 char c; 28 if (c=nc(),c==EOF)return 0; //EOF 29 while(c!='-'&&(c<'0'||c>'9'))c=nc(); 30 int sgn =(c=='-')?-1:1; 31 ret=(c=='-')?0:(c - '0'); 32 while(c=nc(),c>='0'&&c<='9') ret=ret*10+(c-'0'); 33 ret *= sgn; 34 return 1; 35 } 36 template <class T> 37 inline void print(T x) { 38 if(x>9) print(x/10); 39 putchar(x%10+'0'); 40 } 41 }; using fastIO::read; 42 43 const int N = 1e5 + 5; 44 45 int seg[N<<2]; 46 int c[N<<2]; 47 48 void build(int l, int r, int rt) 49 { 50 seg[rt] = c[rt] = 0; 51 if (l == r) { 52 return ; 53 } 54 int mid = (l+r) >> 1; 55 build(lson); 56 build(rson); 57 } 58 59 void pushdown(int rt) 60 { 61 if (c[rt]) { 62 seg[rt<<1] += c[rt]; 63 seg[rt<<1|1] += c[rt]; 64 c[rt<<1] += c[rt]; 65 c[rt<<1|1] += c[rt]; 66 } 67 c[rt] = 0; 68 } 69 70 void update(int L, int R, int x, int l, int r, int rt) 71 { 72 if (L <= l && r <= R) { 73 seg[rt] += x; 74 c[rt] += x; 75 return ; 76 } 77 pushdown(rt); 78 int mid = (l + r) >> 1; 79 if (L <= mid) update(L, R, x, lson); 80 if (mid < R) update(L, R, x, rson); 81 seg[rt] = max(seg[rt<<1], seg[rt<<1|1]); 82 } 83 84 int query(int x, int l, int r, int rt) 85 { 86 if (l == r) { 87 return l; 88 } 89 pushdown(rt); 90 int mid = (l + r) >> 1; 91 if (seg[rt<<1] == x) return query(x, lson); 92 else return query(x, rson); 93 } 94 95 vector<int> p[N]; 96 int a[N]; 97 98 int main() 99 { 100 int n, c, k; 101 while (read(n)) { 102 read(c); read(k); 103 for (int i = 1; i <= c; ++ i) { 104 p[i].clear(); 105 p[i].emplace_back(0); 106 } 107 for (int i = 1; i <= n; ++ i) { 108 read(a[i]); 109 } 110 build(1, n, 1); 111 int ans = 0; 112 for (int i = 1; i <= n; ++ i) { 113 p[a[i]].emplace_back(i); 114 int siz = p[a[i]].size(); 115 update(i, i, c, 1, n, 1); 116 update(p[a[i]][siz - 2] + 1, i, -1, 1, n, 1); 117 if (siz > k) { 118 update(p[a[i]][siz - k - 1] + 1, p[a[i]][siz - k], 1, 1, n, 1); 119 } 120 if (seg[1] < c) continue; 121 int l = query(c, 1, n, 1); 122 ans = max(ans, i - l + 1); 123 } 124 printf("%d\n", ans); 125 } 126 return 0; 127 }