题目链接: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. 原生JS元素怎么取消事件

    关于原生JS元素怎么取消事件,有3种方式 常规方法:removeEventListener 案例: <body> <div id="myDIV"> div ...

  2. Redis-位图法实现简单统计

    比如一个网站有1亿个用户, 现在要统计一周内连续登录的用户 方法: 可以用一个字节8个位表示7个人, 首位不算固定为0, 若某人周一登录则置为1, 没登录则为0 127.0.0.1:6379> ...

  3. C#之异步

    C#之异步 异步是相对于同步而言.跟多线程不能同一而论.异步简单而言好比一个人两双手可以同时做两件以上不同的事情.多线程好比多个人做不同或相同的事情. 异步跟多线程有什么关系? 异步可以分为CPU异步 ...

  4. spring mvc4使用及json 日期转换解决方案

    spring mvc使用注解方式配制,以及对rest风格的支持,真是完美致极.下面将这两天研究到的问题做个总结,供参考.1.request对象的获取方式1:在controller方法上加入reques ...

  5. [js高手之路]es6系列教程 - 解构详解

    解构通俗点说,就是通过一种特定格式,快捷的读取对象/数组中的数据的方法, es6之前,我们通过对象名称[键] 读取数据 var User = { 'name' : 'ghostwu', 'age' : ...

  6. struts2相关简单介绍

    一 Struts2环境配置 1.准备jar包,核心jar包有: 2.创建Struts2项目并导入jar包 3.在Struts2项目中src下创建Struts.xml配置文件 4.在Web.xml文件中 ...

  7. ABP+AdminLTE+Bootstrap Table权限管理系统第十一节--bootstrap table之用户管理列表

    这张开始bootstrap table,引入项目有两种方法,一种是直接去官网下载 地址:http://bootstrap-table.wenzhixin.net.cn/ 另一种是Nuget引入. 然后 ...

  8. 安卓http源码查看器详解

    1.效果图如下,输入网址就可以看到该网址的源码

  9. Linux 粘着位(sticky bit)

    当设置粘着位时只有root或者owner才能删除.重命名文件. 示例: 用户apple默认组为fruit. [root@titan ~]# id apple uid=1001(apple) gid=1 ...

  10. [JLOI2013]删除物品 树状数组

    当时考试时间剩下太短了然后就挂掉了..其实是个简单的数据结构. 话说一看最小还以为是动规呢.. 将两堆头对头排.比如样例就是 541|273 因为是必须有优先级次序,依次拿的话,看优先级大小相邻的两个 ...