zoukankan      html  css  js  c++  java
  • UOJ#274. 【清华集训2016】温暖会指引我们前行

    寒冬又一次肆虐了北国大地

    无情的北风穿透了人们御寒的衣物

    可怜虫们在冬夜中发出无助的哀嚎

    “冻死宝宝了!”

    这时

    远处的天边出现了一位火焰之神

    “我将赐予你们温暖和希望!”

    只见他的身体中喷射出火焰之力

    通过坚固的钢铁,传遍了千家万户

    这时,只听见人们欢呼

    “暖气来啦!”

    任务描述

    虽然小R住的宿舍楼早已来了暖气,但是由于某些原因,宿舍楼中的某些窗户仍然开着(例如厕所的窗户),这就使得宿舍楼中有一些路上的温度还是很低。

    小R的宿舍楼中有nn个地点和一些路,一条路连接了两个地点,小R可以通过这条路从其中任意一个地点到达另外一个地点。但在刚开始,小R还不熟悉宿舍楼中的任何一条路,所以他会慢慢地发现这些路,他在发现一条路时还会知道这条路的温度和长度。每条路的温度都是互不相同的。

    小R需要在宿舍楼中活动,每次他都需要从一个地点到达另一个地点。小R希望每次活动时经过一条最温暖的路径,最温暖的路径的定义为,将路径上各条路的温度从小到大排序后字典序最大。即温度最低的路温度尽量高,在满足该条件的情况下,温度第二低的路温度尽量高,以此类推。小R不会经过重复的路。由于每条路的温度互不相同,因此只存在一条最温暖的路径。

    对于小R的每次活动,你需要求出小R需要走过的路径总长度。如果小R通过当前发现的路不能完成这次活动,则输出 1−1。

    注意本题中的字典序与传统意义上的字典序定义有所不同,对于两个序列a,b(ab)a,b(a≠b),若aa是bb的前缀则aa的字典序较大,同时可以推出空串的字典序最大。

    输入格式

    第一行两个正整数 n,mn,m。表示小R的宿舍楼中有 nn 个地点,共发生了 mm 个事件。

    接下来 mm 行,每行描述一个事件,事件分为三类。

    1. find id u v t lfind id u v t l 表示小R发现了一条连接uu和vv之间的路,编号为idid。相同idid的边只会出现一次。

    2. move u vmove u v 表示小R要从uu到达vv,你需要计算出最温暖的路径的长度 ,若不能从uu到达vv,则输出1−1。

    3. change id lchange id l 表示从uu到vv这条边的长度变为了ll(保证在当前时间点这条边存在)。

    输出格式

    对于每个询问,输出一行整数,表示最温暖的路径长度。

    样例一

    input

    8 19
    find 0 0 2 7 2
    find 1 2 4 4 4
    find 2 4 6 10 1
    find 3 6 7 8 6
    move 2 7
    move 1 6
    find 4 2 5 3 4
    move 0 5
    change 0 12
    find 5 4 5 5 10
    find 6 2 3 6 9
    move 3 5
    find 7 0 1 12 1
    move 1 6
    find 8 1 7 11 100
    move 1 6
    move 3 7
    move 5 6
    move 2 2
    
    

    output

    11
    -1
    6
    23
    18
    106
    122
    11
    0
    
    

    样例二

    input

    15 45
    find 0 1 0 8 5987
    find 1 2 0 14 5455
    find 2 3 0 27 8830
    find 3 4 3 42 7688
    find 4 5 0 25 1756
    find 5 6 5 35 1550
    find 6 7 4 43 9440
    move 3 9
    change 2 9113
    move 10 13
    move 3 3
    move 11 10
    find 7 8 7 6 7347
    find 8 9 8 26 8935
    move 8 4
    change 3 4466
    find 9 10 9 28 8560
    move 6 5
    find 10 11 10 31 6205
    change 9 9228
    find 11 12 10 23 948
    find 12 13 12 45 5945
    move 0 9
    move 2 5
    change 2 6118
    find 13 14 13 12 6906
    move 4 1
    change 2 504
    find 14 4 2 22 9796
    move 10 7
    move 1 14
    move 13 3
    find 15 12 9 39 8985
    find 16 9 8 17 3710
    change 1 5370
    find 17 1 0 36 4669
    find 18 7 6 37 8087
    move 9 0
    find 19 14 9 33 8234
    find 20 0 4 24 5209
    change 1 4883
    find 21 6 3 9 2461
    find 22 5 2 19 4291
    change 1 7219
    change 6 4846
    
    

    output

    -1
    -1
    0
    -1
    16787
    1550
    39301
    7211
    16571
    25510
    59706
    46309
    30692
    
    

    样例三

    见样例数据下载

    限制与约定

    对于find操作:(0id<m,0u,v<n,uv,0t1000000000,0l10000)(0≤id<m,0≤u,v<n,u≠v,0≤t≤1000000000,0≤l≤10000);

    对于move操作:(0u,v<n)(0≤u,v<n);

    对于change操作:(0l10000)(0≤l≤10000)。

    对于100%的数据,1n100000,1m3000001≤n≤100000,1≤m≤300000 。

    本题共有20个数据点,每个数据点5分。

    测试点nnmm其它
    121−2 20≤20 50≤50 无特殊约定
    353−5 1000≤1000 3000≤3000
    6106−10 100000≤100000 300000≤300000 所有的find事件都在move事件之前,且没有change事件
    111411−14 所有的find事件都在move事件之前
    152015−20 无特殊约定

    时间限制2s2s

    空间限制512MB

    树 动态生成树 LCT

    题意看着麻烦,其实就是动态维护最大生成树

    二十分钟敲完,脑抽写错cut调了一小时

    就很气。

    第119行:断边的时候,当然要断那条边和它的原端点,然而一开始写成了断目标边和现在要加的边的端点。←蠢

    代码调来调去变得各种慢,失去了观赏价值(说得仿佛原来有价值一样)

      1 /*by SilverN*/
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<vector>
      8 using namespace std;
      9 const int INF=0x3f3f3f3f;
     10 const int mxn=400010;
     11 int read(){
     12     int x=0,f=1;char ch=getchar();
     13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     15     return x*f;
     16 }
     17 struct edge{
     18     int x,y,m;
     19 }e[mxn];
     20 int id[mxn];
     21 struct node{
     22     int ch[mxn][2],fa[mxn];
     23     bool rev[mxn];
     24     //
     25     int tmp[mxn],val[mxn],smm[mxn];
     26     int mi[mxn],mipos[mxn];
     27     //
     28     int st[mxn],top;
     29     inline bool isroot(int x){return (ch[fa[x]][0]!=x && ch[fa[x]][1]!=x);}
     30     void PD(int x){
     31         if(rev[x]){
     32             int &lc=ch[x][0],&rc=ch[x][1];
     33             swap(lc,rc);
     34             rev[lc]^=1;    rev[rc]^=1;
     35             rev[x]^=1;
     36         }
     37         return;
     38     }
     39     void pushup(int x){
     40         int lc=ch[x][0],rc=ch[x][1];
     41         smm[x]=smm[lc]+smm[rc]+val[x];
     42         mi[x]=tmp[x],mipos[x]=x;
     43         if(mi[lc]<mi[x]){mi[x]=mi[lc];mipos[x]=mipos[lc];}
     44         if(mi[rc]<mi[x]){mi[x]=mi[rc];mipos[x]=mipos[rc];}
     45         return;
     46     }
     47     void rotate(int &x){
     48         int y=fa[x],z=fa[y],lc,rc;
     49         if(ch[y][0]==x)lc=0;else lc=1; rc=lc^1;
     50         if(!isroot(y)){ch[z][ch[z][1]==y]=x;}
     51         fa[x]=z;fa[y]=x;fa[ch[x][rc]]=y;
     52         ch[y][lc]=ch[x][rc];
     53         ch[x][rc]=y;
     54         pushup(y);
     55         return;
     56     }
     57     void Splay(int x){
     58         st[top=1]=x;
     59         for(int i=x;!isroot(i);i=fa[i])st[++top]=fa[i];
     60         while(top)PD(st[top--]);
     61         while(!isroot(x)){
     62             int y=fa[x],z=fa[y];
     63             if(!isroot(y)){
     64                 if((ch[y][0]==x)^(ch[z][0]==y))rotate(x);
     65                 else rotate(y);
     66             }
     67             rotate(x);
     68         }
     69         pushup(x);
     70         return;
     71     }
     72     void access(int x){
     73         for(int y=0;x;x=fa[x]){
     74             Splay(x);
     75             ch[x][1]=y;
     76             pushup(x);
     77             y=x;
     78         }
     79         return;
     80     }
     81     void mkroot(int x){
     82         access(x);Splay(x);
     83         rev[x]^=1;
     84         return;
     85     }
     86     int find(int x){
     87         access(x);Splay(x);
     88         while(ch[x][0])x=ch[x][0];
     89         return x;
     90     }
     91     inline void link(int x,int y){
     92         mkroot(x);fa[x]=y;
     93         return;
     94     }
     95     void cut(int x,int y){
     96         mkroot(x);
     97         access(y);
     98         Splay(y);
     99         if(ch[y][0]==x){fa[x]=0;ch[y][0]=0;}
    100         pushup(y);
    101         return;
    102     }
    103     void change(int x,int l){
    104         access(x);Splay(x);
    105         val[x]=l;
    106         pushup(x);
    107         return;
    108     }
    109     int query(int x,int y){
    110         if(find(x)!=find(y))return -1;
    111         mkroot(x);access(y);Splay(y);
    112         return smm[y];
    113     }
    114     void add(int u,int v,int x){
    115         if(find(u)==find(v)){
    116             query(u,v);
    117             if(mi[v]>=tmp[x])return;
    118             int tar=mipos[v];
    119             cut(e[id[tar]].x,tar);cut(tar,e[id[tar]].y);
    120         }
    121         link(u,x);link(x,v);
    122         return;
    123     }
    124 }Lt;
    125 int n,m,cnt;
    126 char op[30];
    127 int main(){
    128     int i,j,u,v,w,l;
    129     n=read();m=read();
    130     for(i=0;i<=n;i++){
    131         Lt.tmp[i]=Lt.mi[i]=INF;
    132         Lt.val[i]=Lt.val[i]=0;
    133         Lt.mipos[i]=i;
    134     }
    135     cnt=n;
    136     for(i=1;i<=m;i++){
    137         scanf("%s",op);
    138         switch(op[0]){
    139             case 'f':{
    140                 ++cnt;j=read();
    141                 id[cnt]=j;u=read()+1;v=read()+1;w=read();l=read();
    142                 e[j].x=u;e[j].y=v;e[j].m=cnt;
    143                 Lt.smm[cnt]=Lt.val[cnt]=l;
    144                 Lt.mi[cnt]=Lt.tmp[cnt]=w;Lt.mipos[cnt]=cnt;
    145                 Lt.add(u,v,cnt);
    146                 break;
    147             }
    148             case 'm':{
    149                 u=read()+1;v=read()+1;
    150                 int res=Lt.query(u,v);
    151                 printf("%d
    ",res);
    152                 break;
    153             }
    154             case 'c':{
    155                 u=read();l=read();
    156                 Lt.change(e[u].m,l);
    157                 break;
    158             }
    159         }
    160     }
    161     return 0;
    162 }
  • 相关阅读:
    POJ 1330 Nearest Common Ancestors(LCA Tarjan算法)
    LCA 最近公共祖先 (模板)
    线段树,最大值查询位置
    带权并查集
    转负二进制
    UVA 11437 Triangle Fun
    UVA 11488 Hyper Prefix Sets (字典树)
    UVALive 3295 Counting Triangles
    POJ 2752 Seek the Name, Seek the Fame (KMP)
    UVA 11584 Partitioning by Palindromes (字符串区间dp)
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6593227.html
Copyright © 2011-2022 走看看