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 }
View Code

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 }
View Code

 

posted @ 2019-07-28 21:32  UtopioSPH  阅读(163)  评论(0编辑  收藏  举报