[UOJ30/Codeforces Round #278 E]Tourists
好毒瘤的一道题QAQ,搞了好几好几天。
UOJ上卡在了53个点,CF上过了,懒得优化常数了
刚看时一眼Tarjan搞个强连通分量然后缩点树链剖分xjb搞搞就行了,然后写完了,然后WA了QAQ。
思考了一会把代码全删了,加了个mulutiset重写一遍,然后又是各种WA。
然后去看了POPOQQQ大爷的代码。原来把无向图缩成一个树用的是点双联通分量,搞不清图论的概念只能自扇脸..
然后去研究了点双联通分量,搞了一道题,顺便给Trajn搞了个小总结。
这道题其实就是缩点然后剖剖剖。但是我的姿势不太对,而且中间也有一些细节。
先点双缩成一颗树,然后对于每个点双新建一虚点,点双中的每个割点向虚点连边。这样最好形成的树的每一条路径就一定是 虚点-割点-虚点-割点.....
剩下的任务是不是就是敲剖分的模板了?
并不是hhh。考虑修改操作,每次修改的如果非割点,更新这个点所在的点双就行了也就是树中的虚点。但是如果修改的点是割点的话,就需要更新这个割点所连接的每个点双,因为一个割点可以属于多个点双。如果出题人给你搞个菊花图你就GG了。
PS.对于修改操作,需要用STL里的$multiset$,代码如下:
struct BCC{
int v;msi s;
inline void insert(int num){s.insert(num);v=*s.begin();}
inline void change(int x,int y){s.erase(s.find(x));s.insert(y);v=*s.begin();}
}bcc[MAXN];
换个思路,如果更新割点需要更新所连接的每个点双,那么在查询一个点双的时候是否可以顺便查询他的父亲(必为割点)?
所以在查询的时候,如果当前点是虚点,再查询一下父亲就OK了。
//UOJ 30 Fuck this problem
//by Cydiater
//2016.11.1
#include <iostream>
#include <iomanip>
#include <map>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctime>
#include <bitset>
#include <queue>
using namespace std;
#define ll long long
#define up(i,j,n) for(int i=j;i<=n;i++)
#define down(i,j,n) for(int i=j;i>=n;i--)
#define cmax(a,b) a=max(a,b)
#define cmin(a,b) a=min(a,b)
#define Auto(i,node) for(int i=LINK[node];i;i=e[i].next)
#define msi multiset<int>
const int MAXN=2e5+5;
const int oo=0x3f3f3f3f;
inline int read(){
char ch=getchar();int x=0,f=1;
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int N,M,Q,Val[MAXN],stack[MAXN],top=0,dfn[MAXN],low[MAXN],dfs_clock=0,group[MAXN],group_num=0,fa[MAXN][25],dep[MAXN],son[MAXN],siz[MAXN],Pos[MAXN],Top[MAXN],val[MAXN],cnt=0;
int t[MAXN<<3],k,v,L,R,LEN=0;
bool iscut[MAXN];
char opt;
struct edge{int x,y,next;}u[MAXN<<1];
struct BCC{
int v;msi s;
inline void insert(int num){s.insert(num);v=*s.begin();}
inline void change(int x,int y){s.erase(s.find(x));s.insert(y);v=*s.begin();}
}bcc[MAXN];
inline void Inserter(int x,int y){u[++LEN].x=x;u[LEN].y=y;}
struct Graph{
int LINK[MAXN],len;
edge e[MAXN<<2];
inline void insert(int x,int y){e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;}
inline void Insert(int x,int y){insert(x,y);insert(y,x);}
void tarjan(int node){
dfn[node]=low[node]=++dfs_clock;
stack[++top]=node;
Auto(i,node)if(!dfn[e[i].y]){
tarjan(e[i].y);
cmin(low[node],low[e[i].y]);
if(low[e[i].y]>=dfn[node]){
group_num++;int tmp;iscut[node]=1;
do{
tmp=stack[top--];
group[tmp]=group_num;
if(iscut[tmp])Inserter(tmp+N,group_num);
}while(tmp!=e[i].y);
Inserter(node+N,group_num);
}
}else cmin(low[node],dfn[e[i].y]);
}
void dfs1(int node,int deep,int father){
dep[node]=deep;fa[node][0]=father;son[node]=0;
int max_siz=0;siz[node]=1;
Auto(i,node)if(e[i].y!=father){
dfs1(e[i].y,deep+1,node);
if(siz[e[i].y]>max_siz){
max_siz=siz[e[i].y];
son[node]=e[i].y;
}
}
}
void dfs2(int node,int tp){
Top[node]=tp;Pos[node]=++cnt;val[cnt]=bcc[node].v;
if(son[node])dfs2(son[node],tp);
Auto(i,node)if(e[i].y!=fa[node][0]&&e[i].y!=son[node])
dfs2(e[i].y,e[i].y);
}
int LCA(int x,int y){
if(x==y) return x;
if(dep[x]<dep[y])swap(x,y);
down(i,18,0)if(dep[x]-(1<<i)>=dep[y])x=fa[x][i];
if(x==y) return x;
down(i,18,0)if(fa[x][i]!=0&&fa[x][i]!=fa[y][i]){
x=fa[x][i];y=fa[y][i];
}
return fa[x][0];
}
}G1,G2;
namespace solution{
inline void reload(int root){t[root]=min(t[root<<1],t[root<<1|1]);}
void init(){
N=read();M=read();Q=read();
up(i,1,N)Val[i]=read();
up(i,1,M){
int x=read(),y=read();
G1.Insert(x,y);
}
}
void build(int leftt,int rightt,int root){
if(leftt==rightt){t[root]=val[leftt];return;}
int mid=(leftt+rightt)>>1;
build(leftt,mid,root<<1);
build(mid+1,rightt,root<<1|1);
reload(root);
}
inline void updata(int leftt,int rightt,int root){
if(leftt==rightt){
t[root]=v;return;
}
int mid=(leftt+rightt)>>1;
if(k>mid)updata(mid+1,rightt,root<<1|1);
if(k<=mid)updata(leftt,mid,root<<1);
reload(root);
}
inline int Get(int leftt,int rightt,int root){
if(leftt>=L&&rightt<=R) return t[root];
int mid=(leftt+rightt)>>1;
if(L>=mid+1) return Get(mid+1,rightt,root<<1|1);
else if(R<=mid) return Get(leftt,mid,root<<1);
else return min(Get(leftt,mid,root<<1),Get(mid+1,rightt,root<<1|1));
}
inline int get(int node,int lca){
int ans=oo;
while(Top[node]!=Top[lca]){
L=Pos[Top[node]];R=Pos[node];
cmin(ans,Get(1,cnt,1));
node=fa[Top[node]][0];
}
L=Pos[lca];R=Pos[node];
cmin(ans,Get(1,cnt,1));
return ans;
}
void get_ancestor(){
up(i,1,20)up(node,1,N<<1)if(fa[node][i-1])
fa[node][i]=fa[fa[node][i-1]][i-1];
}
void slove(){
memset(iscut,0,sizeof(iscut));
G1.tarjan(1);
up(i,1,LEN){
int x=u[i].x,y=u[i].y;
G2.Insert(x,y);
}
up(i,1,N){
if(i!=1)bcc[group[i]].insert(Val[i]);
if(iscut[i])bcc[i+N].insert(oo);
}
G2.dfs1(N+1,0,0);G2.dfs2(N+1,N+1);
build(1,cnt,1);get_ancestor();
while(Q--){
scanf("%c",&opt);
if(opt=='C'){
int x=read(),y=read();
if(x!=1){
bcc[group[x]].change(Val[x],y);
k=Pos[group[x]];v=bcc[group[x]].v;
updata(1,cnt,1);
}
Val[x]=y;
}else{
int x=read(),y=read();
if(x==y){
printf("%d\n",Val[x]);
continue;
}
x=iscut[x]?x+N:group[x];
y=iscut[y]?y+N:group[y];
int lca=G2.LCA(x,y),ans=oo;
if(lca<=group_num)lca=fa[lca][0];
ans=Val[lca-N];
cmin(ans,min(get(x,lca),get(y,lca)));
printf("%d\n",ans);
}
}
}
}
int main(){
//freopen("input.in","r",stdin);
using namespace solution;
init();
slove();
return 0;
}
[UOJ30/Codeforces Round #278 E]Tourists的更多相关文章
- UOJ30——【CF Round #278】Tourists
1.感谢taorunz老师 2.题目大意:就是给个带权无向图,然后有两种操作, 1是修改某个点的权值 2是询问,询问一个值,就是u到v之间经过点权的最小值(不可以经过重复的点) 操作数,点数,边数都不 ...
- uoj30【CF Round #278】Tourists(圆方树+树链剖分+可删除堆)
- 学习了一波圆方树 学习了一波点分治 学习了一波可删除堆(巧用 ? STL) 传送门: Icefox_zhx 注意看代码看怎么构建圆方树的. tips:tips:tips:圆方树内存记得开两倍 CO ...
- Codeforces Round #278 (Div. 2)
题目链接:http://codeforces.com/contest/488 A. Giga Tower Giga Tower is the tallest and deepest building ...
- Brute Force - B. Candy Boxes ( Codeforces Round #278 (Div. 2)
B. Candy Boxes Problem's Link: http://codeforces.com/contest/488/problem/B Mean: T题目意思很简单,不解释. ana ...
- Codeforces Round #278 (Div. 1) B. Strip multiset维护DP
B. Strip Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/487/problem/B De ...
- Codeforces Round #278 (Div. 1) A. Fight the Monster 暴力
A. Fight the Monster Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/487/ ...
- CodeForces Round #278 (Div.2) (待续)
A 这么简单的题直接贴代码好了. #include <cstdio> #include <cmath> using namespace std; bool islucky(in ...
- Codeforces Round #278 (Div. 1)
A A monster is attacking the Cyberland! Master Yang, a braver, is going to beat the monster. Yang an ...
- UOJ #30. 【CF Round #278】Tourists
Description Cyberland 有 n 座城市,编号从 1 到 n,有 m 条双向道路连接这些城市.第 j 条路连接城市 aj 和 bj.每天,都有成千上万的游客来到 Cyberland ...
随机推荐
- Nginx反向代理和负载均衡部署指南
1. 安装 1) 从Nginx官网下载页面(http://nginx.org/en/download.html)下载Nginx最新版本(目前是1.5.13版本)安装包: ...
- AngularJs中,如何在render完成之后,执行Js脚本
AngularJs是Google开源的前端JS框架.使用AngularJs, 我们能够容易地.健壮的开发出类似于Gmail一样的单页Web应用.AngularJs这个新兴的MVC前端框架,具有以下特点 ...
- 微软源代码管理工具TFS2013安装与使用详细图文教程(Vs2013)
这篇文章联合软件小编主要介绍了微软源代码管理工具TFS2013安装与使用图文教程,本文详细的给出了TFS2013的安装配置过程.使用教程,需要的朋友可以参考下 最近公司新开发一个项目要用微软的TFS2 ...
- SSRS 2008 R2 错误:Timeout expired. The timeout period
今天遇到了Reporting Services(SQL SERVER 2008 R2)的报表执行异常情况,报表加载数据很长时间都没有响应,最后报"An error occurred with ...
- ORACLE的SQL JOIN方式小结
在ORACLE数据库中,表与表之间的SQL JOIN方式有多种(不仅表与表,还可以表与视图.物化视图等联结),官方的解释如下所示 A join is a query that combines row ...
- web应用中使用JavaMail发送邮件 。。转载
现在很多的网站都提供有用户注册功能, 通常我们注册成功之后就会收到一封来自注册网站的邮件.邮件里面的内容可能包含了我们的注册的用户名和密码以及一个激活账户的超链接等信息.今天我们也来实现一个这样的功能 ...
- SQL Like模糊查询一些小知识
模糊查询: where mc like '值':返回值等同于where mc ='值' where mc like '%值':匹配 名称是 '*值'(以“值”作为结尾)的所有数据,*表示任何值任何长度 ...
- 【转载】 Java线程面试题 Top 50
Java线程面试题 Top 50 不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题.Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员 的欢迎.大多数待遇丰厚的J ...
- Nova 组件详解 - 每天5分钟玩转 OpenStack(26)
本节开始,我们将详细讲解 Nova 的各个子服务. 前面架构概览一节知道 Nova 有若干 nova-* 的子服务,下面我们将依次学习最重要的几个.今天先讨论 nova-api 和 nova-cond ...
- git 中关于LF 和 CRLF 的问题
git 中关于LF 和 CRLF 的转换问题注意: Windows下编辑器设置中,建议调整设置为Unix风格.(具体设置位置各种编辑器上不同,需要找找) 使用Git Bash进行命令行操作时,运行一下 ...