题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6200

题意:给个图,有2种操作,一种是加一条无向边,二是查询u,v之间必须有的边的条数,所谓必须有的边就是对于u,v必须通过这条边才能到达。

解法:一个很简单的想法,搞出图上的一颗树,然后剩下的边当成询问点队加到更新点集,每加入一个更新点对,直接把u,v区间的值置为0即可,查询就直接区间求和,可以直接树剖来维护,简单暴力,读入挂卡过。还有1个log的做法,可以用LCT维护(这个没写,口胡的)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
typedef long long LL;
struct edge{
int to,next;
edge(){}
edge(int to,int next):to(to),next(next){}
}E[maxn*2];
struct FastIO
{
static const int S = 1310720;
int wpos;
char wbuf[S];
FastIO() : wpos(0) {}
inline int xchar()
{
static char buf[S];
static int len = 0, pos = 0;
if (pos == len)
pos = 0, len = fread(buf, 1, S, stdin);
if (pos == len) return -1;
return buf[pos ++];
}
inline int xuint()
{
int c = xchar(), x = 0;
while (c <= 32) c = xchar();
for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
return x;
}
inline int xint()
{
int s = 1, c = xchar(), x = 0;
while (c <= 32) c = xchar();
if (c == '-') s = -1, c = xchar();
for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
return x * s;
}
inline void xstring(char *s)
{
int c = xchar();
while (c <= 32) c = xchar();
for (; c > 32; c = xchar()) * s++ = c;
*s = 0;
}
inline void wchar(int x)
{
if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0;
wbuf[wpos ++] = x;
}
inline void wint(LL x)
{
if (x < 0) wchar('-'), x = -x;
char s[24];
int n = 0;
while (x || !n) s[n ++] = '0' + x % 10, x /= 10;
while (n--) wchar(s[n]);
}
inline void wstring(const char *s)
{
while (*s) wchar(*s++);
}
~FastIO()
{
if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
}
} io;
int n, m, head[maxn],edgecnt, tim;
int sz[maxn], top[maxn], son[maxn], dep[maxn];
int fa[maxn],tid[maxn];
void init(){
memset(head,-1,sizeof(head));
memset(son,-1,sizeof(son));
edgecnt=tim=0;
}
void add(int u,int v){
E[edgecnt].to=v,E[edgecnt].next=head[u],head[u]=edgecnt++;
}
void dfs1(int u, int father, int d){
dep[u]=d;
fa[u]=father;
sz[u]=1;
for(int i=head[u]; i+1; i=E[i].next){
int v=E[i].to;
if(v!=father){
dfs1(v,u,d+1);
sz[u]+=sz[v];
if(son[u]==-1||sz[v]>sz[son[u]]) son[u]=v;
}
}
}
void dfs2(int u, int tp){
top[u]=tp;
tid[u]=++tim;
if(son[u]==-1) return;
dfs2(son[u],tp);
for(int i=head[u];i+1;i=E[i].next){
int v=E[i].to;
if(v!=son[u]&&v!=fa[u])
dfs2(v,v);
}
}
namespace DSU{
int fa1[maxn];
void init1(){
for(int i=1; i<maxn; i++) fa1[i]=i;
}
int find_set(int x){
if(x==fa1[x]) return x;
else return fa1[x] = find_set(fa1[x]);
}
bool union_set(int x, int y){
x = find_set(x);
y = find_set(y);
if(x!=y){
fa1[x]=y;
return 1;
}
else{
return 0;
}
}
}
using namespace DSU;
namespace SegmentTree{
int sum[maxn<<2], lazy[maxn<<2];
void pushup(int rt){
sum[rt]=sum[rt*2]+sum[rt*2+1];
}
void pushdown(int rt){
if(lazy[rt]){
lazy[rt*2]=lazy[rt];
lazy[rt*2+1]=lazy[rt];
sum[rt*2]=sum[rt*2+1]=0;
lazy[rt]=0;
}
}
void build(int l, int r, int rt){
lazy[rt] = 0;
if(l == r){
sum[rt] = l!=1;
return;
}
int mid = (l+r)/2;
build(l,mid,rt*2);
build(mid+1,r,rt*2+1);
pushup(rt);
}
void update(int L, int R, int l, int r, int rt){
if(L<=l&&r<=R){
lazy[rt]=1;
sum[rt]=0;
return;
}
pushdown(rt);
int mid=(l+r)/2;
if(L<=mid) update(L,R,l,mid,rt*2);
if(mid<R) update(L,R,mid+1,r,rt*2+1);
pushup(rt);
}
int query(int L, int R, int l, int r, int rt){
if(L<=l&&r<=R) return sum[rt];
int mid=(l+r)/2;
pushdown(rt);
int ret=0;
if(L<=mid) ret+=query(L,R,l,mid,rt*2);
if(mid<R) ret+=query(L,R,mid+1,r,rt*2+1);
return ret;
}
void update(int u, int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
update(tid[top[u]], tid[u], 1, tim, 1);
u = fa[top[u]];
}
if(u == v) return;
if(dep[u]<dep[v]) swap(u,v);
update(tid[v]+1,tid[u],1,tim,1);
}
int query(int u, int v){
int ret=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
ret += query(tid[top[u]], tid[u], 1, tim, 1);
u = fa[top[u]];
}
if(u==v) return ret;
if(dep[u]<dep[v]) swap(u,v);
ret += query(tid[v]+1,tid[u],1,tim,1);
return ret;
}
}
using namespace SegmentTree;
int main()
{
int T,q,ks=0;
T = io.xint();
while(T--){
printf("Case #%d:\n", ++ks);
n = io.xint();
m = io.xint();
init();
init1();
vector <pair<int, int> > G;
for(int i=1; i<=m; i++){
int u, v;
u = io.xint();
v = io.xint();
if(union_set(u,v)){
add(u, v);
add(v, u);
}else{
G.emplace_back(u, v);
}
}
dfs1(1,0,0);
dfs2(1,1);
build(1,n,1);
for(auto &it:G){
update(it.first,it.second);
}
q = io.xint();
for(int i=1; i<=q; i++){
int op,x,y;
op = io.xint();
x = io.xint();
y = io.xint();
if(op==1)
update(x, y);
else{
printf("%d\n", query(x,y));
}
}
}
return 0;
}

HDU 6200 2017沈阳网络赛 树上区间更新,求和的更多相关文章

  1. HDU 6203 2017沈阳网络赛 LCA,DFS+树状数组

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6203 题意:n+1 个点 n 条边的树(点标号 0 ~ n),有若干个点无法通行,导致 p 组 U V ...

  2. HDU 6201 2017沈阳网络赛 树形DP或者SPFA最长路

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6201 题意:给出一棵树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过 ...

  3. HDU 6199 2017沈阳网络赛 DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6199 题意:n堆石子,Alice和Bob来做游戏,一个人选择取K堆那么另外一个人就必须取k堆或者k+1 ...

  4. HDU 6205 2017沈阳网络赛 思维题

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6205 题意:给你n堆牌,原本每一堆的所有牌(a[i]张)默认向下,每次从第一堆开始,将固定个数的牌(b ...

  5. HDU 6198 2017沈阳网络赛 线形递推

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6198 题意:给出一个数k,问用k个斐波那契数相加,得不到的数最小是几. 解法:先暴力打表看看有没有规律 ...

  6. HDU 6195 2017沈阳网络赛 公式

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6195 题意:有M个格子,有K个物品.我们希望在格子与物品之间连数量尽可能少的边,使得——不论是选出M个 ...

  7. HDU 6197 array array array 2017沈阳网络赛 LIS

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6197 题意:给你n个数,问让你从中删掉k个数后(k<=n),是否能使剩下的序列为非递减或者非递增 ...

  8. HDU 6194 string string string 2017沈阳网络赛 后缀数组

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6194 题意:告诉你一个字符串和k , 求这个字符串中有多少不同的子串恰好出现了k 次. 解法:后缀数组 ...

  9. HDU 6194 string string string ——(2017沈阳网络赛,后缀数组)

    思路见:http://blog.csdn.net/aozil_yang/article/details/77929216. 代码如下: #include <stdio.h> #includ ...

随机推荐

  1. RabbitMQ入门-消息派发那些事儿

    在上篇<RabbitMQ-高效的Work模式>中,我们了解了Work模型,该模型包括一个生产者,一个消息队列和多个消费者. 我们已经通过实例看出消息队列中的消息是如何被一个或者多个消费者消 ...

  2. dubbo源码分析(二):超时原理以及应用场景

    dubbo超时原理以及应用场景 *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: ...

  3. java中的各种数据类型在内存中存储的方式

    原文地址:http://blog.csdn.net/aaa1117a8w5s6d/article/details/8251456 1.Java是如何管理内存的 java的内存管理就是对象的分配和释放问 ...

  4. POJ-1861-NETWORK 解题报告

    Network Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 16628   Accepted: 6597   Specia ...

  5. (转载)Stackoverflow评选的C++推荐书单

    C++必读书籍推荐 (原链接:http://bestcbooks.com/recommended-cpp-books 2013-10-07) 本文内容来自国外著名编程问答网站Stackoverflow ...

  6. Node.js Up and Runing 学习日记(一)

    认识一个Node.js程序 HTTP模块是专为快速非阻塞式HTTP服务器而用C重新编写的. 1. var http = require('http'); 2. http.createServer(fu ...

  7. solr排序问题

         搜搜引擎排序问题,因为涉及到的维度比较多,有时候单纯的依靠sort是无法满足需要的,例如:搜索商品的时候我希望不管怎么排无货的商品都置底,这样问题就来了,怎么排? 其实,solr是自己的解决 ...

  8. Mongodb相关 (Shell命令 / mongoose)

    Mongodb相关 1.创建一个文件夹作为数据库存放的目录 2.打开cmd cd到Mongodb/bin目录去 3.执行mongod --dbpath "第一项创建的文件夹(数据库数据存放目 ...

  9. Docker 搭建开发环境

    本文介绍如何将Docker集成到开发环境,自动构建应用,并使容器拥有独立的内网IP为开发人员提供服务. 术语解释 Docker镜像:一个不可修改的"模板",每个代码版本对应一个镜像 ...

  10. 看了看 #ifndef 和#pragma once 的区别

    刚开始学习程序的时候,老师就说过用#ifndef 这样的结构防止头文件被重复包含,所以就没有关心那么多.今天可能由于自家底层系统缘故,陈工说最好还是用#pragma once ,于是查了下两个的区别, ...