UOJ274 [清华集训2016] 温暖会指引我们前行 【LCT】【最大生成树】

题目分析:

差评,最大生成树裸题。hack数据还卡常。

代码:

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3
  4 const int maxn = 402000;
  5
  6 struct LCT{
  7     int fa[maxn],lazy[maxn],ch[maxn][2],d1[maxn],d2[maxn];
  8     int val[maxn],tot[maxn],num;
  9     stack<int> sta;
 10     void push_up(int now){
 11     val[now] = min(d1[now],min(val[ch[now][0]],val[ch[now][1]]));
 12     tot[now] = d2[now] + tot[ch[now][0]] + tot[ch[now][1]];
 13     }
 14     void push_down(int now){
 15     if(lazy[now]){
 16         swap(ch[now][0],ch[now][1]);
 17         lazy[now]=0;
 18         lazy[ch[now][0]] ^= 1; lazy[ch[now][1]] ^= 1;
 19         lazy[0] = 0;
 20     }
 21     }
 22     int is_root(int now){return !(ch[fa[now]][0]==now||ch[fa[now]][1]==now);}
 23     void r0(int now,int dr){
 24     int ff = fa[now],gf = fa[ff],son = ch[now][dr];
 25     int flag = is_root(ff);
 26     ch[ff][dr^1] = son; fa[son] = ff;
 27     ch[now][dr] = ff; fa[ff] = now;
 28     fa[now] = gf;
 29     if(!flag){if(ch[gf][0] == ff) ch[gf][0] = now; else ch[gf][1] = now;}
 30     push_up(ff); push_up(now);
 31     fa[0] = 0;ch[0][0] = ch[0][1] = 0;
 32     }
 33     void splay(int now){
 34     int pp = now;
 35     while(!is_root(pp)) sta.push(pp),pp = fa[pp];
 36     sta.push(pp);
 37     while(!sta.empty()) push_down(sta.top()),sta.pop();
 38     while(!is_root(now)){
 39         if(is_root(fa[now])){
 40         if(ch[fa[now]][0] == now) r0(now,1); else r0(now,0);
 41         }else{
 42         int ff = fa[now],gf = fa[ff];
 43         int alpha = ch[gf][0]==ff,beta = ch[ff][0]==now;
 44         if(alpha^beta) r0(now,beta),r0(now,alpha);
 45         else r0(ff,alpha),r0(now,beta);
 46         }
 47     }
 48     }
 49     void access(int now){
 50     splay(now);ch[now][1] = 0;push_up(now);
 51     while(fa[now]){
 52         int nxt=fa[now];splay(nxt);ch[nxt][1]=now; push_up(nxt); now=nxt;
 53     }
 54     }
 55     void make_root(int now){
 56     access(now);
 57     splay(now);
 58     lazy[now] ^= 1;
 59     }
 60     void cut(int u,int v){
 61     make_root(u); access(v); splay(u);
 62     fa[v] = 0;
 63     if(ch[u][0] == v) ch[u][0] = 0; else ch[u][1] = 0;
 64     push_up(u);
 65     }
 66     void link(int u,int v){make_root(u); fa[u] = v;}
 67     int lft(int dt){
 68     splay(dt);
 69     if(lazy[dt]) push_down(dt);
 70     while(ch[dt][0]){
 71         dt = ch[dt][0];
 72         if(lazy[dt]) push_down(dt);
 73     }
 74     return dt;
 75     }
 76     int find_min(int now){
 77     splay(now);
 78     while(d1[now] != val[now]){
 79         if(val[ch[now][0]] == val[now]) now = ch[now][0];
 80         else now = ch[now][1];
 81     }
 82     return now;
 83     }
 84 }T;
 85
 86 int n,m,pre[maxn];
 87
 88 struct edge{int from,to,tmp,len;}edges[maxn];
 89
 90 char str[7];
 91
 92 int found(int x){
 93     int rx = x; while(pre[rx] != rx) rx = pre[rx];
 94     while(pre[x]!=rx){int tt = x; pre[x] = rx; x = tt;}
 95     return rx;
 96 }
 97
 98 void work(){
 99     T.d1[0] = 2e9;T.val[0] = 2e9;T.d2[0] = 0;
100     for(int i=1;i<=n;i++){T.num++;T.d1[i] = 2e9; T.val[i] = 2e9; pre[i] = i;}
101     for(int i=1;i<=m;i++){
102     scanf("%s",str);
103     if(str[0] == ‘f‘){
104         int id;scanf("%d",&id);
105         scanf("%d%d",&edges[id].from,&edges[id].to);
106         scanf("%d%d",&edges[id].tmp,&edges[id].len);
107         edges[id].from++;edges[id].to++;
108         T.d1[n+id+1] = edges[id].tmp; T.d2[n+id+1] = edges[id].len;
109         T.val[n+id+1] = edges[id].tmp; T.tot[n+id+1] = edges[id].len;
110         T.make_root(edges[id].from);
111         T.access(edges[id].to);
112          int pd = T.lft(edges[id].to);
113         if(pd == edges[id].from){
114         if(T.val[edges[id].to] > edges[id].tmp) continue;
115         int pla = T.find_min(edges[id].to);
116         T.make_root(pla);T.cut(pla,edges[pla-n-1].from);
117         T.cut(pla,edges[pla-n-1].to);
118         }
119         T.link(edges[id].from,n+id+1);T.link(edges[id].to,n+id+1);
120         pre[found(edges[id].from)] = found(edges[id].to);
121     }else{
122         if(str[0] == ‘m‘){
123         int u,v; scanf("%d%d",&u,&v); v++;u++;
124         if(found(u) != found(v)){puts("-1");continue;}
125         T.make_root(u);    T.access(v); T.splay(v);
126         printf("%d\n",T.tot[v]);
127         }else{
128         int id,l; scanf("%d%d",&id,&l);
129         T.make_root(n+id+1); T.d2[n+id+1] = l;
130         T.push_up(n+id+1);
131         }
132     }
133     }
134 }
135
136 int main(){
137     scanf("%d%d",&n,&m);
138     work();
139     return 0;
140 }

原文地址:https://www.cnblogs.com/Menhera/p/9347557.html

时间: 2024-10-09 18:20:22

UOJ274 [清华集训2016] 温暖会指引我们前行 【LCT】【最大生成树】的相关文章

【UOJ274】【清华集训2016】温暖会指引我们前行 LCT

[UOJ274][清华集训2016]温暖会指引我们前行 任务描述 虽然小R住的宿舍楼早已来了暖气,但是由于某些原因,宿舍楼中的某些窗户仍然开着(例如厕所的窗户),这就使得宿舍楼中有一些路上的温度还是很低. 小R的宿舍楼中有n个地点和一些路,一条路连接了两个地点,小R可以通过这条路从其中任意一个地点到达另外一个地点.但在刚开始,小R还不熟悉宿舍楼中的任何一条路,所以他会慢慢地发现这些路,他在发现一条路时还会知道这条路的温度和长度.每条路的温度都是互不相同的. 小R需要在宿舍楼中活动,每次他都需要从

bzoj 4736 /uoj274【清华集训2016】温暖会指引我们前行 lct

[清华集训2016]温暖会指引我们前行 统计 描述 提交 自定义测试 寒冬又一次肆虐了北国大地 无情的北风穿透了人们御寒的衣物 可怜虫们在冬夜中发出无助的哀嚎 “冻死宝宝了!” 这时 远处的天边出现了一位火焰之神 “我将赐予你们温暖和希望!” 只见他的身体中喷射出火焰之力 通过坚固的钢铁,传遍了千家万户 这时,只听见人们欢呼 “暖气来啦!” 任务描述 虽然小R住的宿舍楼早已来了暖气,但是由于某些原因,宿舍楼中的某些窗户仍然开着(例如厕所的窗户),这就使得宿舍楼中有一些路上的温度还是很低. 小R的

BZOJ 4736 温暖会指引我们前行 LCT+最优生成树+并查集

题目链接:http://uoj.ac/problem/274 题意概述: 没什么好概述的......概述了题意就知道怎么做了...... 分析: 就是用lct维护最大生成树. 然后如果去UOJ上面交发现如果不用并查集判断连通性就要T?! 然后我就默默改了并查集...(hash表并查集输入输出占据了一半的行数?!) 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdl

UOJ 274 【清华集训2016】温暖会指引我们前行 ——Link-Cut Tree

魔法森林高清重置, 只需要维护关于t的最大生成树,然后链上边权求和即可. 直接上LCT 调了将近2h 吃枣药丸 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i&g

[清华集训] 温暖会指引我们前行

同样是LCT维护一个类似最大生成树的东西. 题目链接:戳我 emmm其实我在uoj上过不去,加的数据我TLE了...... 关于push_up的小trick:初始化的时候给0节点也初始化成最大值,然后push_up的时候不用管自己的左右儿子是否为空,直接返回左右儿子中比较小的一个就可以了,然后再和自己作比较.qwqwq 代码如下: #include<iostream> #include<cstdio> #include<cstring> #include<algo

[BZOJ4730][清华集训2016][UOJ266] Alice和Bob又在玩游戏

题意:俩智障又在玩游戏.规则如下: 给定n个点,m条无向边(m<=n-1),保证无环,对于每一个联通块,编号最小的为它们的根(也就是形成了一片这样的森林),每次可以选择一个点,将其本身与其祖先全部删除,不能操作者输.判断先手胜负. 题解:比较神的一道题. 我们现在要解决的问题是怎么求解一棵子树的SG值,首先把根删掉的情况考虑,这很好办,直接把子树的sg异或起来就好,关键是如果删除点在子树里怎么办. 这里用到了一个巧妙的东西,trie.怎么会用这个呢?因为删除子树里的节点就相当于是子树里这种对应的

【UOJ】#273. 【清华集训2016】你的生命已如风中残烛

题目链接:http://uoj.ac/problem/273 $${Ans=\frac{\prod _{i=1}^{m}i}{w-n+1}}$$ 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib> 6 #include<cmath> 7 #include<cstring> 8

【20161203-20161208】清华集训2016滚粗记&amp;&amp;酱油记&amp;&amp;游记

先挖坑(这个blog怎么变成游记专用了--) #include <cstdio> using namespace std; int main(){ puts("转载请注明出处:http://www.cnblogs.com/wangyurzee7/"); puts("谢谢您的配合"); puts("by wangyurzee7"); return 0; }

[UOJ274]温暖会指引我们前行

看春晚不如写题... 第一次写维护边权的题,因为懒所以没学边权lct,写的是插入虚点存边权,但我猜两种写法的效率应该差不多 要求最低温度尽量高,所以只能走最高温度生成树上的边,用lct维护就行了 lct维护最大生成树,每加一条边$\left(x,y,T\right)$,如果两边不连通就直接连,如果连通且树上$x\rightarrow y$的最低温度$\geq T$,那么不用加边,否则删掉树上路径最低温的边,加入新边 个人觉得这种插入虚点维护边权的写法挺方便的 #include<stdio.h>