• bzoj 4336[BJOI2015]骑士的旅行


    4336: BJOI2015 骑士的旅行

    Time Limit: 20 Sec  Memory Limit: 512 MB

    Description

    在一片古老的土地上,有一个繁荣的文明。
    这片大地几乎被森林覆盖,有N座城坐落其中。巧合的是,这N座城由恰好N-1条双向道路连接起来,使得任意两座城都是连通的。
    也就是说,这些城形成了树的结构,任意两座城之间有且仅有一条简单路径。
    在这个文明中,骑士是尤其受到尊崇的职业。任何一名骑士,都是其家族乃至家乡的荣耀。Henry从小就渴望成为一名能守护家乡、驱逐敌人的骑士。勤奋训练许多年后,Henry终于满18岁了。他决定离开家乡,向那些成名已久的骑士们发起挑战!根据Henry的调查,大陆上一共有M名受封骑士,不妨编号为1到M。
    第i个骑士居住在城Pi,武力值为Fi。Henry计划进行若干次旅行,每次从某座城出发沿着唯一的简单路径前往另一座城,
    同时会挑战路线上武力值最高的K个骑士(Henry的体力有限,为了提高水平,当然要挑战最强的骑士)。如果路线上的骑士不足K人,Henry会挑战遇到的所有人。
    每次旅行前,可能会有某些骑士的武力值或定居地发生变化,Henry自然会打听消息,并对计划做出调整。
    为了在每次旅行时做好充分准备,Henry希望你能帮忙在每次旅行前计算出这条路线上他将挑战哪些对手。
     

    Input

    第一行,一个整数N,表示有N座城,编号为1~N。
    接下来N-1行,每行两个整数Ui和Vi,表示城Ui和城Vi之间有一条道路相连。
    第N+1行,一个整数M,表示有M个骑士。
    接下来M行,每行两个整数Fi和Pi。按顺序依次表示编号为1~M的每名骑士的武
    力值和居住地。
    第N+M+2行,两个整数Q,K,分别表示操作次数和每次旅行挑战的骑士数目上限。
    接下来Q行,每行三个整数Ti,Xi,Yi。Ti取值范围为{1,2,3},表示操作类型。
    一共有以下三种类型的操作:
    Ti=1时表示一次旅行,Henry将从城Xi出发前往城市Yi;
    Ti=2时表示编号为Xi的骑士的居住地搬到城Yi;
    Ti=3时表示编号为Xi的骑士的武力值修正为Yi。

    Output

    输出若干行,依次为每个旅行的答案。
    对每个Ti=1的询问,输出一行,按从大到小的顺序输出Henry在这次旅行中挑战的
    所有骑士的武力值。如果路线上没有骑士,输出一行,为一个整数-1。

    Sample Input

    5
    1 2
    1 3
    2 4
    2 5
    4
    10 1
    6 1
    14 5
    7 3
    5 3
    1 2 3
    1 5 3
    1 4 4
    2 1 4
    1 2 3

    Sample Output

    10 7 6
    14 10 7
    -1
    7 6

    HINT

    100%的数据中,1 ≤ N, M ≤ 40,000,1 ≤ Ui, Vi, Pi ≤ N,1 ≤ Q ≤ 80,000, 1 ≤ K ≤ 

    20,旅行次数不超过 40,000 次,武力值为不超过1,000的正整数。 
     
     
    对于这类树上问题,可以考虑树链剖分解决
    重点是如何维护前k大个
    对于一个单点,可以用muiliset 直接按顺序存储所有的人
    这样向上合并的时候就用归并的思想很简单就解决了。
     
     
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <set>
      6 #define LL long long
      7 
      8 using namespace std;
      9 
     10 const int MAXN = 5e4 + 10;
     11 
     12 int T;
     13 int x, y;
     14 multiset<int> city[MAXN];
     15 int ans[30];
     16 int N, M;
     17 int head[MAXN];
     18 int m[MAXN];
     19 int cnt = 0;
     20 int vis[MAXN];
     21 int dfn[MAXN], top[MAXN], fa[MAXN];
     22 int size[MAXN], son[MAXN];
     23 int deep[MAXN];
     24 int Q, K;
     25 
     26 struct edge {
     27     int v;
     28     int next;
     29 } g[MAXN * 2];
     30 
     31 struct segment {
     32     int l, r;
     33     int big[30];
     34 } seg[MAXN * 20];
     35 
     36 struct knight {
     37     int force, loc;
     38 } kt[MAXN];
     39 
     40 void addedge(int u, int v)
     41 {
     42     g[++cnt].v = v;
     43     g[cnt].next = head[u];
     44     head[u] = cnt;
     45 }
     46 
     47 inline LL read()
     48 {
     49     LL x = 0, w = 1; char ch = 0;
     50     while(ch < '0' || ch > '9') {
     51         if(ch == '-') {
     52             w = -1;
     53         }
     54         ch = getchar();
     55     }
     56     while(ch >= '0' && ch <= '9') {
     57         x = x * 10 + ch - '0';
     58         ch = getchar();
     59     }
     60     return x * w;
     61 }
     62 
     63 void pushup(int x)
     64 {
     65     int l1 = 1, l2 = 1;
     66     for(int i = 1; i <= K; i++) {
     67         if(seg[x * 2].big[l1] >= seg[x * 2 + 1].big[l2]) {
     68             seg[x].big[i] = seg[x * 2].big[l1++];
     69         } else {
     70             seg[x].big[i] = seg[x * 2 + 1].big[l2++];
     71         }
     72     }
     73 }
     74 
     75 void merge(int x)
     76 {
     77     int temp[30];
     78     int l1 = 1, l2 = 1;
     79     for(int i = 1; i <= K; i++) {
     80         temp[i] = ans[i];
     81     }
     82     for(int i = 1; i <= K; i++) {
     83         if(temp[l1] >= seg[x].big[l2]) {
     84             ans[i] = temp[l1++];
     85         } else {
     86             ans[i] = seg[x].big[l2++];
     87         }
     88     }
     89 }
     90 
     91 void dfs1(int x)
     92 {
     93     deep[x] = deep[fa[x]] + 1;
     94     size[x] = 1;
     95     vis[x] = 1;
     96     for(int j = head[x]; j; j = g[j].next) {
     97         int to = g[j].v;
     98         if(!vis[to]) {
     99             fa[to] = x;
    100             dfs1(to);
    101             size[x] += size[to];
    102             if(size[to] > size[son[x]]) {
    103                 son[x] = to;
    104             }
    105         }
    106     }
    107 }
    108 
    109 void dfs2(int x, int k)
    110 {
    111     top[x] = k;
    112     dfn[x] = ++cnt;
    113     m[cnt] = x;
    114     if(son[x]) {
    115         dfs2(son[x], k);
    116     }
    117     for(int j = head[x]; j; j = g[j].next) {
    118         int to = g[j].v;
    119         if(!dfn[to]) {
    120             dfs2(to, to);
    121         }
    122     }
    123 }
    124 
    125 void update(int u, int l, int r, int root, int k)
    126 {
    127     if(l == r) {
    128         city[m[l]].insert(k);
    129         multiset<int>::iterator t;
    130         int i = 1;
    131         t = city[m[l]].end();
    132         t--;
    133         for(; i <= K; i++, t--) {
    134             seg[root].big[i] = *t;
    135             if(t == city[m[l]].begin()) {
    136                 i++;
    137                 for(; i <= K; i++) {
    138                     seg[root].big[i] = 0;
    139                 }
    140                 break;
    141             }
    142         }
    143         return;
    144     }
    145     int mid = (l + r) >> 1;
    146     if(u <= mid) {
    147         update(u, l, mid, root * 2, k);
    148     } else {
    149         update(u, mid + 1, r, root * 2 + 1, k);
    150     }
    151     pushup(root);
    152 }
    153 
    154 void del(int u, int l, int r, int root, int k)
    155 {
    156     if(l == r) {
    157         multiset<int> :: iterator t;
    158         t = city[m[l]].find(k);
    159         city[m[l]].erase(t);
    160         int i = 1;
    161         t = city[m[l]].end();
    162         if(city[m[l]].empty()) {
    163             for(int i = 1; i <= K; i++) {
    164                 seg[root].big[i] = 0;
    165             }
    166             return;
    167         }
    168         t--;
    169         for(; i <= K; i++, t--) {
    170             seg[root].big[i] = *t;
    171             if(t == city[m[l]].begin()) {
    172                 i++;
    173                 for(;i <= K; i++) {
    174                     seg[root].big[i] = 0;
    175                 }
    176                 break;
    177             }
    178         }
    179         return;
    180     }
    181     int mid = (l + r) >> 1;
    182     if(u <= mid) {
    183         del(u, l, mid, root * 2, k);
    184     } else {
    185         del(u, mid + 1, r, root * 2 + 1, k);
    186     }
    187     pushup(root);
    188 }
    189 
    190 void build()
    191 {
    192     dfs1(1);
    193     cnt = 0;
    194     dfs2(1, 1);
    195 }
    196 
    197 void query(int ql, int qr, int l, int r, int root)
    198 {
    199     if(l >= ql && r <= qr) {
    200         merge(root);
    201         return;
    202     }
    203     int mid = (l + r) >> 1;
    204     if(mid >= ql) {
    205         query(ql, qr, l, mid, root * 2);
    206     }
    207     if(mid < qr) {
    208         query(ql, qr, mid + 1, r, root * 2 + 1);
    209     }
    210 }
    211 
    212 int LCA(int x, int y)
    213 {
    214     int fx = top[x], fy = top[y];
    215     while(fx != fy) {
    216         if(deep[fx] >= deep[fy]) {
    217             query(dfn[fx], dfn[x], 1, N, 1);
    218             x = fa[fx];
    219             fx = top[x];
    220         } else {
    221             query(dfn[fy], dfn[y], 1, N, 1);
    222             y = fa[fy];
    223             fy = top[y];
    224         }
    225     }
    226     if(deep[x] >= deep[y]) {
    227         query(dfn[y], dfn[x], 1, N, 1);
    228         return y;
    229     } else {
    230         query(dfn[x], dfn[y], 1, N, 1);
    231         return x;
    232     }
    233 }
    234 
    235 int main()
    236 { 
    237     //freopen("knight10.in", "r", stdin);
    238     //freopen("knight.out", "w", stdout);
    239     N = read();
    240     for(int i = 1; i < N; i++) {
    241         int u = read(), v = read();
    242         addedge(u, v);
    243         addedge(v, u);
    244     }
    245     build();
    246     M = read();
    247     for(int i = 1; i <= M; i++) {
    248         kt[i].force = read(), kt[i].loc = read();
    249     } 
    250     Q = read(), K = read();
    251     for(int i = 1; i <= M; i++) {
    252         update(dfn[kt[i].loc], 1, N, 1, kt[i].force);
    253     }
    254     int tot = 1;
    255     while(Q--) {
    256         /*cout<<tot++<<endl;
    257         multiset<int> ::iterator t;
    258         t = city[4527].begin();
    259         for(; t != city[4527].end(); t++) {
    260             cout<<*t<<" ";
    261         }
    262         cout<<endl;*/ 
    263         T = read();
    264         x = read(), y = read();
    265         //cout<<T<<" "<<x<<" "<<y<<endl; 
    266         if(T == 1) {
    267             for(int i = 1; i <= K; i++) {
    268                 ans[i] = 0;
    269             }
    270             /*if(x == 1 && y == 2){
    271                 multiset<int> ::iterator t;
    272                 t = city[x].begin();
    273                 for(; t != city[x].end(); t++) {
    274                     cout<<*t<<" ";
    275                 }
    276                 cout<<endl;
    277                 
    278             }*/
    279             LCA(x, y);
    280             /*for(int i = 1; i <= N; i++) {
    281                 for(int j = 1; j <= 20; j++) {
    282                     ans[j] = 0;
    283                 }
    284                 query(dfn[i], dfn[i], 1, N, 1);
    285                 for(int j = 1; j <= 3; j++) {
    286                     cout<<ans[j]<<" ";
    287                 }
    288                 cout<<endl<<endl;
    289             }*/
    290             for(int i = 1; i <= K; i++) {
    291                 if(ans[i] == 0) {
    292                     if(i == 1) {
    293                         printf("-1");
    294                     }
    295                     break;
    296                 }
    297                 printf("%d ", ans[i]);
    298             }
    299             printf("
    ");
    300         } else if(T == 2) {
    301             /*if(x == 720 && y == 6713) {
    302                 cout<<dfn[kt[x].loc] <<" "<<kt[x].force<<" "<<kt[x].loc<<endl;
    303                 multiset<int> ::iterator t;
    304                 t = city[kt[x].loc].begin();
    305                 for(; t != city[kt[x].loc].end(); t++) {
    306                     cout<<*t<<" ";
    307                 }
    308                 cout<<endl;
    309                 return 0;
    310             }*/
    311             del(dfn[kt[x].loc], 1, N, 1, kt[x].force);
    312             kt[x].loc = y;
    313             update(dfn[kt[x].loc], 1, N, 1, kt[x].force);
    314         } else {
    315             del(dfn[kt[x].loc], 1, N, 1, kt[x].force);
    316             kt[x].force = y;
    317             update(dfn[kt[x].loc], 1, N, 1, kt[x].force);
    318         }
    319     }
    320 }    
    321 
    322 
    323 /*
    324 5 
    325 
    326 1 2 
    327 
    328 1 3 
    329 
    330 2 4 
    331 
    332 2 5 
    333 
    334 4 
    335 
    336 10 1 
    337 
    338 6 1 
    339 
    340 14 5 
    341 
    342 7 3 
    343 
    344 5 3 
    345 
    346 1 2 3 
    347 
    348 1 5 3 
    349 
    350 1 4 4 
    351 
    352 2 1 4 
    353 
    354 1 2 3 
    355 
    356 */
    View Code
     
  • 相关阅读:
    搭建自己的博客(九):使用shell模式批量添加博客文章并增加分页功能
    搭建自己的博客(八):使用fontawesome框架来添加图标以及美化详情页
    linux系列(十):cat命令
    linux系列(九):touch命令
    搭建自己的博客(七):使用bootstrap框架美化导航栏
    linux系列(八):cp命令
    搭建自己的博客(六):添加首页,使用css对界面做美化
    linux系列(七):mv命令
    Re-enable extensions not coming from Chrome Web Store on Chrome v35+ (with enhanced security)
    liblensfun 在 mingw 上编译时遇到的奇怪问题
  • 原文地址:https://www.cnblogs.com/wuenze/p/8570576.html
Copyright © 2020-2023  润新知