• bupt summer training for 16 #5 ——数据结构


    https://vjudge.net/contest/173780

    A.假设 Pt = i,则由Ppi = i得

    Ppt = t = Pi

    所以就有 if Pt = i then Pi = t

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 using namespace std;
     5 
     6 int n, a[110];
     7 
     8 int main() {
     9     scanf("%d", &n);
    10     if(n & 1) puts("-1");
    11     else {
    12         for(int i = 1;i <= n;i ++)
    13             a[i] = i;
    14         for(int i = 1;i <= n;i += 2)
    15             swap(a[i], a[i + 1]);
    16         for(int i = 1;i <= n;i ++)
    17             printf("%d ", a[i]);
    18     }
    19 }
    View Code

    B.

    C.treap练手题,STL_set练手题,链表练手题

    set用的不熟所以直接上的链表

    排序后时间倒序来看的思路

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 using namespace std;
     5 
     6 typedef long long ll;
     7 
     8 const int maxn = 50010;
     9 
    10 int n, b[maxn];
    11 
    12 ll ans;
    13 
    14 struct List{
    15     int next, last;
    16 }c[maxn];
    17 
    18 struct node{
    19     ll x;
    20     int y;
    21     bool operator < (const node &a) const {
    22         return x < a.x;
    23     }
    24 }a[maxn];
    25 
    26 int main() {
    27     scanf("%d", &n);
    28     for(int i = 1;i <= n;i ++)
    29         scanf("%lld", &a[i].x), a[i].y = i;
    30     ans = a[1].x;
    31     a[0].x = -1000000000000ll;
    32     a[n + 1].x = 1000000000000ll;
    33     sort(a + 1, a + n + 1);
    34     for(int i = 1;i <= n;i ++) b[a[i].y] = i;
    35     for(int i = 1;i <= n;i ++) {
    36         c[i].next = i + 1;
    37         c[i].last = i - 1;
    38     }
    39     for(int i = n;i > 1;i --) {
    40         ans += min(a[b[i]].x - a[c[b[i]].last].x, a[c[b[i]].next].x - a[b[i]].x);
    41         c[c[b[i]].last].next = c[b[i]].next;
    42         c[c[b[i]].next].last = c[b[i]].last;
    43     }
    44     printf("%lld
    ", ans);
    45     return 0;
    46 }
    View Code

    D.边权给点,点修改和路径查询

    直接上树剖+线段树,考场写狗

    多组数据需要clear存边的vector,fa 和 son

    修改的时候bel[i]找到第 i 条边权给的点

    还要对应该点在线段树上的叶节点位置!

      1 #include <cstdio>
      2 #include <vector>
      3 #include <algorithm>
      4 
      5 using namespace std;
      6 
      7 const int maxn = 10010;
      8 
      9 int Case, n, M;
     10 
     11 struct Edge{
     12     int v, w, num;
     13 };
     14 
     15 vector <Edge> edge[maxn];
     16 
     17 char str[10];
     18 
     19 int a, b, tr[maxn << 2];
     20 
     21 int bel[maxn], siz[maxn], son[maxn], val[maxn];
     22 
     23 int cnt, fa[maxn], dep[maxn], pos[maxn], dfn[maxn], top[maxn];
     24 
     25 void dfs1(int u) {
     26     siz[u] = 1;
     27     for(int v, i = 0;i < edge[u].size();i ++) {
     28         v = edge[u][i].v;
     29         if(v == fa[u]) continue;
     30         fa[v] = u;
     31         dep[v] = dep[u] + 1;
     32         val[v] = edge[u][i].w;
     33         bel[edge[u][i].num] = v;
     34         dfs1(v), siz[u] += siz[v];
     35         if(siz[son[u]] < siz[v]) son[u] = v;
     36     }
     37 }
     38 
     39 void dfs2(int u, int tp) {
     40     top[u] = tp, pos[u] = ++ cnt, dfn[cnt] = u;
     41     if(son[u]) dfs2(son[u], tp);
     42     for(int v, i = 0;i < edge[u].size();i ++)  {
     43         v = edge[u][i].v;
     44         if(v != fa[u] && v != son[u])
     45             dfs2(v, v);
     46     }
     47 }
     48 
     49 void change(int i, int x) {
     50     i = pos[i];
     51     for(tr[i += M] = x, i >>= 1;i;i >>= 1)
     52         tr[i] = max(tr[i << 1], tr[i << 1 | 1]);
     53 }
     54 
     55 int mmax(int s, int t) {
     56     int res = -666666666;
     57     for(s += M - 1, t += M + 1;s ^ t ^ 1;s >>= 1, t >>= 1) {
     58         if(~ s & 1) res = max(res, tr[s ^ 1]);
     59         if(  t & 1) res = max(res, tr[t ^ 1]);
     60     }
     61     return res;
     62 }
     63 
     64 void query(int u, int v) {
     65     int fu = top[u], fv = top[v], res = -666666666;
     66     while(fu != fv) {
     67         if(dep[fu] < dep[fv]) swap(u, v), swap(fu, fv);
     68         res = max(res, mmax(pos[fu], pos[u]));
     69         u = fa[fu], fu = top[u];
     70      }
     71      if(u == v) printf("%d
    ", res);
     72      else {
     73          if(dep[u] < dep[v]) swap(u, v);
     74          printf("%d
    ", max(res, mmax(pos[v] + 1, pos[u])));
     75      }
     76 }
     77 
     78 int main() {
     79 //freopen("test.txt","r",stdin);
     80     val[1] = -666666666;
     81     int u, v, w;
     82     scanf("%d", &Case);
     83     while(Case --) {
     84         cnt = 0;
     85         scanf("%d", &n);
     86         for(int i = 1;i <= n;i ++) edge[i].clear(), fa[i] = son[i] = 0;
     87         for(int i = 1;i < n;i ++) {
     88             scanf("%d %d %d", &u, &v, &w);
     89             edge[u].push_back((Edge){v, w, i});
     90             edge[v].push_back((Edge){u, w, i});
     91         }
     92         dfs1(1), dfs2(1, 1);
     93         for(M = 1;M < n + 2; M <<= 1);
     94         for(int i = 1;i <= n;i ++) tr[i + M] = val[dfn[i]];
     95         for(int i = n + 1;i <= M + 1;i ++) tr[i + M] = val[1];
     96         for(int i = M;i;i --) tr[i] = max(tr[i << 1], tr[i << 1 | 1]);
     97         while(scanf("%s", str), str[0] != 'D') {
     98             if(str[0] == 'C') scanf("%d %d", &a, &b), change(bel[a], b);
     99             else scanf("%d %d", &a, &b), query(a, b);
    100         }
    101         puts("");
    102     }
    103 }
    View Code

    E.考场上脑补出来一个正解,可惜只差了一步

    两个单调队列,一增一减,从前向后扫

    当扫到某个位置,最大差距 > R 时

    踢出两个队列中位置最靠前的元素直至差距 <= R

    如果这是最大差距 >= L 则更新答案即可

    时间复杂度O(n),别人说这是个做过的RMQ啊...

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 using namespace std;
     5 
     6 const int maxn = 100010;
     7 
     8 int n, x, y, m, a[maxn], q1[maxn], q2[maxn];
     9 
    10 int l1, r1, l2, r2, t;
    11 
    12 int main() {
    13     while(scanf("%d %d %d", &n, &x, &y) != EOF) {
    14         for(int i = 1;i <= n;i ++)
    15             scanf("%d", &a[i]);
    16         m = t = 0, l1 = l2 = 1, r1 = r2 = 0;
    17         for(int i = 1;i <= n;i ++) {
    18             while(l1 <= r1 && a[i] > a[q1[r1]]) r1 --;
    19             q1[++ r1] = i;
    20             while(l2 <= r2 && a[i] < a[q2[r2]]) r2 --;
    21             q2[++ r2] = i;
    22             while(l1 <= r1 && l2 <= r2 && a[q1[l1]] > a[q2[l2]] + y) {
    23                 if(q1[l1] < q2[l2]) t = q1[l1 ++];
    24                 else t = q2[l2 ++];
    25             }
    26             if(l1 <= r1 && l2 <= r2 && a[q1[l1]] >= a[q2[l2]] + x) m = max(m, i - t);
    27         }
    28         printf("%d
    ", m);
    29     }
    30     return 0;
    31 }
    View Code

    F.就是枚举min,然后单调队列求出左右拓展多远就好了

     1 #include <cstdio>
     2 
     3 const int maxn = 100010;
     4 
     5 int l = 1, r, q[maxn];
     6 
     7 int L, R, n, a[maxn], b[maxn], c[maxn];
     8 
     9 long long ans = -1, tmp, s[maxn];
    10 
    11 int main() {
    12     scanf("%d", &n);
    13     for(int i = 1;i <= n;i ++)
    14         scanf("%d", &a[i]), s[i] = a[i] + s[i - 1];
    15     for(int i = 1;i <= n;i ++) {
    16         while(l <= r && a[i] < a[q[r]]) b[q[r]] = i - q[r], r --;
    17         q[++ r] = i;
    18     }
    19     while(l <= r) b[q[r]] = n + 1 - q[r], r --;
    20     l = 1, r = 0;
    21     for(int i = n;i;i --) {
    22         while(l <= r && a[i] < a[q[r]]) c[q[r]] = q[r] - i, r --;
    23         q[++ r] = i;
    24     }
    25     while(l <= r) c[q[r]] = q[r], r --;
    26     for(int i = 1;i <= n;i ++) {
    27         tmp = (s[i + b[i] - 1] - s[i - c[i]]) * a[i];
    28         if(tmp > ans) ans = tmp, L = i - c[i] + 1, R = i + b[i] - 1;
    29     }
    30     printf("%lld
    %d %d", ans, L ,R);
    31     return 0;
    32 }
    View Code

    G.开始没看清题发现大家都会写区间众数?

    连续的相同...线段树傻逼题

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 using namespace std;
     5 
     6 const int maxn = 100010;
     7 
     8 struct node{
     9     int ls, rs, lc, rc, mm;
    10 }tr[maxn << 2];
    11 
    12 int n, m, c[maxn];
    13 
    14 node operator +(const node &a, const node &b) {
    15     node res;
    16     res.ls = a.ls;
    17     res.lc = a.lc;
    18     res.rs = b.rs;
    19     res.rc = b.rc;
    20     res.mm = max(a.mm, b.mm);
    21     if(a.rc == b.lc) {
    22         res.mm = max(res.mm, a.rs + b.ls);
    23         if(a.lc == a.rc) res.ls += b.ls;
    24         if(b.lc == b.rc) res.rs += a.rs;
    25     }
    26     return res;
    27 }
    28 
    29 void build(int o, int l, int r) {
    30     if(l == r) {
    31         tr[o] = (node){1, 1, c[r], c[r], 1};
    32         return;
    33     }
    34     int mid = (l + r) >> 1;
    35     build(o << 1, l, mid);
    36     build(o << 1 | 1, mid + 1, r);
    37     tr[o] = tr[o << 1] + tr[o << 1 | 1];
    38 }
    39 
    40 node ask(int o, int l, int r, int s, int t){
    41     if(s <= l && r <= t) return tr[o];
    42     int mid = (l + r) >> 1;
    43     if(t <= mid) return ask(o << 1, l, mid, s, t);
    44     else if(s > mid) return ask(o << 1 | 1, mid + 1, r, s, t);
    45     else return ask(o << 1, l, mid, s, t) + ask(o << 1 | 1, mid + 1, r, s, t);
    46 }
    47 
    48 int main() {
    49     int a, b;
    50     while(scanf("%d %d", &n, &m), n != 0) {
    51         for(int i = 1;i <= n;i ++)
    52             scanf("%d", &c[i]);
    53         build(1, 1, n);
    54         //printf("%d %d %d
    ",tr[1].mm,tr[6].rc, tr[7].lc);
    55         while(m --) {
    56             scanf("%d %d", &a, &b);
    57             printf("%d
    ", ask(1, 1, n, a, b).mm);
    58         }
    59     }
    60 }
    View Code

    H.

    I.无修改查询树上路径和,随便做啦

    dis[u] + dis[v] - dis[lca] * 2

    我直接上的bfs树剖求lca

     1 #include <cstdio>
     2 #include <vector>
     3 #include <algorithm>
     4 
     5 using namespace std;
     6 
     7 const int maxn = 40010;
     8 
     9 struct Edge{
    10     int v, w;
    11 };
    12 
    13 vector <Edge> edge[maxn];
    14 
    15 int Case, n, m, a, b, c, dis[maxn];
    16 
    17 int l, r, q[maxn], siz[maxn], son[maxn];
    18 
    19 int cnt, fa[maxn], dep[maxn], top[maxn];
    20 
    21 int lca(int u, int v) {
    22     int fu = top[u], fv = top[v];
    23     while(fu != fv) {
    24         if(dep[fu] < dep[fv]) swap(u, v), swap(fu, fv);
    25         u = fa[fu], fu = top[u];
    26      }
    27      return dep[u] < dep[v] ? u : v;
    28 }
    29 
    30 int main() {
    31     int u, v, w;
    32     scanf("%d", &Case);
    33     while(Case --) {
    34         scanf("%d %d", &n, &m);
    35         for(int i = 1;i < n;i ++) {
    36             scanf("%d %d %d", &u, &v, &w);
    37             edge[u].push_back((Edge){v, w});
    38             edge[v].push_back((Edge){u, w});
    39         }
    40         l = r = 0, q[++ r] = 1;
    41         while(l <= r) {
    42             u = q[l ++];
    43             siz[u] = 1, son[u] = top[u] = 0;
    44             for(int i = 0;i < edge[u].size();i ++) {
    45                 v = edge[u][i].v;
    46                 if(v == fa[u]) continue;
    47                 fa[v] = u, q[++ r] = v, dep[v] = dep[u] + 1, dis[v] = dis[u] + edge[u][i].w;
    48             }
    49         }
    50         for(int i = n;i > 1;i --) {
    51             siz[fa[q[i]]] += siz[q[i]];
    52             if(!son[fa[q[i]]] || siz[son[fa[q[i]]]] < siz[q[i]]) son[fa[q[i]]] = q[i];
    53         }
    54         for(int i = 1;i <= n;i ++) {
    55             u = q[i];
    56             if(son[fa[u]] == u) top[u] = top[fa[u]];
    57             else top[u] = u;
    58         }
    59         while(m --) {
    60             scanf("%d %d", &a, &b);
    61             c = lca(a, b);
    62             printf("%d
    ", dis[a] - dis[c] - dis[c] + dis[b]);
    63         }
    64     }
    65 }
    View Code

    J.裸树状数组

     1 #include <cstdio>
     2 
     3 const int maxn = 50010;
     4 
     5 int c[maxn], a[maxn];
     6 
     7 int Case, n, x, y;
     8 
     9 char str[10];
    10 
    11 int lowbit(int x) {
    12     return (x & (-x));
    13 }
    14 
    15 int ask(int i) {
    16     int res = 0;
    17     while(i > 0) res += c[i], i -= lowbit(i);
    18     return res;
    19 }
    20 
    21 void add(int i, int x) {
    22     while(i <= n) c[i] += x, i += lowbit(i);
    23 }
    24 
    25 
    26 int main() {
    27     //freopen("test.txt", "r", stdin);
    28     scanf("%d", &Case);
    29     for(int tt = 1;tt <= Case;tt ++) {
    30         printf("Case %d:
    ", tt);
    31         scanf("%d", &n);
    32         for(int i = 1;i <= n;i ++)
    33             scanf("%d", &a[i]), a[i] += a[i - 1];
    34         while(scanf("%s", str), str[0] != 'E') {
    35             scanf("%d %d", &x, &y);
    36             if(str[0] == 'Q') printf("%d
    ", ask(y) - ask(x - 1) + a[y] - a[x - 1]);
    37             else add(x, y * (str[0] == 'A' ? 1 : -1));
    38         }
    39         for(int i = 1;i <= n;i ++) c[i] = 0;
    40     }
    41     return 0;
    42 }
    View Code

    K.区间加和区间求和,差分树状数组除非有封装好的板子

    不然现场还是只能写线段树

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 using namespace std;
     5 
     6 typedef long long ll;
     7 
     8 const int maxn = 100010;
     9 
    10 int n, m, d[maxn];
    11 
    12 char str[10];
    13 
    14 int a, b, c;
    15 
    16 ll s[maxn];
    17 
    18 struct node{
    19     ll lazy, sum;
    20 }tr[maxn << 2];
    21 
    22 void pushup(int o) {
    23     tr[o].sum = tr[o << 1].sum + tr[o << 1 | 1].sum;
    24 }
    25 
    26 void pushdown(int o, int l, int r) {
    27     if(!tr[o].lazy) return;
    28     int mid = (l + r) >> 1;
    29     tr[o << 1].sum += tr[o].lazy * (mid - l + 1);
    30     tr[o << 1 | 1].sum += tr[o].lazy * (r - mid);
    31     tr[o << 1].lazy += tr[o].lazy;
    32     tr[o << 1 |1].lazy += tr[o].lazy;
    33     tr[o].lazy = 0;
    34 }
    35 
    36 void add(int o, int l, int r, int s, int t, int x) {
    37     if(l != r) pushdown(o, l, r);
    38     if(s <= l && r <= t) {
    39         tr[o].lazy += x;
    40         tr[o].sum += 1ll * x * (r - l + 1);
    41         return;
    42     }
    43     int mid = (l + r) >> 1;
    44     if(s <= mid) add(o << 1, l, mid, s, t, x);
    45     if(mid < t) add(o << 1 | 1, mid + 1, r, s, t, x);
    46     pushup(o);
    47 }
    48 
    49 ll query(int o, int l, int r, int s, int t) {
    50     if(l != r) pushdown(o, l, r);
    51     if(s <= l && r <= t) return tr[o].sum;
    52     ll res = 0;
    53     int mid = (l + r) >> 1;
    54     if(s <= mid) res += query(o << 1, l, mid, s, t);
    55     if(mid < t) res += query(o << 1 | 1, mid + 1, r, s, t);
    56     pushup(o);
    57     return res;
    58 }
    59 
    60 int main(int argc, char const *argv[]){
    61     scanf("%d %d", &n, &m);
    62     for(int i = 1;i <= n;i ++)
    63         scanf("%d", &d[i]), s[i] = s[i - 1] + d[i];
    64     while(m --) {
    65         scanf("%s %d %d", str, &a, &b);
    66         if(str[0] == 'Q') printf("%lld
    ", query(1, 1, n, a, b) + s[b] - s[a - 1]);
    67         else scanf("%d", &c), add(1, 1, n, a, b, c);
    68     }
    69     return 0;
    70 }
    View Code

    L.vector会TLE改邻接表能过...***

    dfs序 + 树状数组

     1 #include <cstdio>
     2 
     3 const int maxn = 200010;
     4 
     5 int n, m, q, a[maxn], c[maxn], st[maxn], en[maxn];
     6 
     7 int tot, head[maxn], to[maxn], next[maxn];
     8 
     9 void ade(int x, int y) {
    10     to[++ tot] = y, next[tot] = head[x], head[x] = tot;
    11 }
    12 
    13 int lowbit(int x) {
    14     return (x & (-x));
    15 }
    16 
    17 int ask(int i) {
    18     int res = 0;
    19     while(i > 0) res += c[i], i -= lowbit(i);
    20     return res;
    21 }
    22 
    23 void add(int i, int x) {
    24     while(i <= n) c[i] += x, i += lowbit(i);
    25 }
    26 
    27 void dfs(int x, int f) {
    28     a[x] = 1, st[x] = ++ m;
    29     for(int y, i = head[x];i;i = next[i]) {
    30         y = to[i];
    31         if(y == f) continue;
    32         dfs(y, x);
    33     }
    34     en[x] = m;
    35 }
    36 
    37 char str[10];
    38 
    39 int x;
    40 
    41 int main() {
    42     scanf("%d", &n);
    43     for(int u, v, i = 1;i < n;i ++) {
    44         scanf("%d %d", &u, &v);
    45         ade(u, v), ade(v, u);
    46     }
    47     dfs(1, 1);
    48     scanf("%d", &q);
    49     while(q --) {
    50         scanf("%s %d", str, &x);
    51         if(str[0] == 'Q') printf("%d
    ", ask(en[x]) - ask(st[x] - 1) + en[x] - st[x] + 1);
    52         else {
    53             if(a[x]) add(st[x], -1), a[x] = 0;
    54             else add(st[x], 1), a[x] = 1;
    55         }
    56     }
    57     return 0;
    58 }
    View Code
  • 相关阅读:
    USACO castle
    【求建议】毕业之声——信院IT类毕业学子经验分享交流会
    需求管理之勇于直面需求变更
    spring boot 配置redis
    java Redis工具类
    java多线程之原子变量
    innerHTML与jquery里的html()区别介绍
    解决IE下select标签innerHTML插入option的BUG(兼容
    【转载】html中object标签详解
    最全的CSS浏览器兼容问题http://www.68design.net/Web-Guide/HTMLCSS/37154-1.html
  • 原文地址:https://www.cnblogs.com/ytytzzz/p/7253869.html
Copyright © 2020-2023  润新知