hdu 5274 树链剖分
Dylans loves tree
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1484 Accepted Submission(s): 347
All nodes have a value A[i].Nodes on tree is numbered by 1∼N.
Then he is given Q questions like that:
①0 x y:change node x′s value to y
②1 x y:For all the value in the path from x to y,do they all appear even times?
For each ② question,it guarantees that there is at most one value that appears odd times on the path.
1≤N,Q≤100000, the value A[i]∈N and A[i]≤100000
(T≤3 and there is at most one testcase that N>1000)
For each testcase:
In the first line there are two numbers N and Q.
Then in the next N−1 lines there are pairs of (X,Y) that stand for a road from x to y.
Then in the next line there are N numbers A1..AN stand for value.
In the next Q lines there are three numbers(opt,x,y).
3 2
1 2
2 3
1 1 1
1 1 2
1 1 3
1
/*
hdu 5274 树链剖分 problem:
给你有一个树,然后有两个操作
1.修改第x个节点的值为y
2.查询x~y路径上哪一个数出现了奇数次 solve:
由于题目保证只可能有一个数出现奇数次那么求 u->v这条链上所有点权的异或值即可
以前用 线段树+lca解决的. 这次是直接用的树链剖分,感觉思路都差不多的. 用一个数组映射当前
节点在线段树上的位置,所以
1:操作可以直接单点更新解决.
2:直接查询链上面的异或值就行. 感觉就是让u,v递推到达最小公共祖先,在过程中查询每一条重链or轻链,再将答案和并起来.
总体上和普通线段树很像 hhh-2016-08-18 15:32:24
*/
#pragma comment(linker,"/STACK:124000000,124000000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#define lson i<<1
#define rson i<<1|1
#define ll long long
#define clr(a,b) memset(a,b,sizeof(a))
#define key_val ch[ch[root][1]][0]
using namespace std;
const int maxn = 200100;
const int inf = 0x3f3f3f3f;
int head[maxn],tot,pos,son[maxn];
int top[maxn],fp[maxn],fa[maxn],dep[maxn],num[maxn],p[maxn];
int n;
struct Edge
{
int to,next;
} edge[maxn<<1]; void ini()
{
tot = 0,pos = 1;
clr(head,-1),clr(son,-1);
// clr(val,0);
} void add_edge(int u,int v)
{
edge[tot].to = v,edge[tot].next = head[u],head[u] = tot++;
} void dfs1(int u,int pre,int d)
{
dep[u] = d;
fa[u] = pre,num[u] = 1;
// cout << "node:" << u<<endl;
for(int i = head[u]; ~i; i = edge[i].next)
{
int v = edge[i].to;
if(v != pre)
{
dfs1(v,u,d+1);
num[u] += num[v];
if(son[u] == -1 || num[v] > num[son[u]])
son[u] = v;
}
}
} void getpos(int u,int sp)
{
top[u] = sp;
p[u] = pos++;
fp[p[u]] = u;
if(son[u] == -1)return ;
getpos(son[u],sp);
for(int i = head[u]; ~i ; i = edge[i].next)
{
int v = edge[i].to;
if(v != son[u] && v != fa[u])
getpos(v,v);
}
} struct node
{
int l,r,mid;
ll Min;
} tree[maxn << 2];
void push_up(int i)
{
tree[i].Min = tree[lson].Min^tree[rson].Min;
}
void build(int i,int l,int r)
{
tree[i].l = l,tree[i].r = r;
tree[i].Min = inf;
tree[i].mid=(l+r) >>1;
if(l == r)
{
// cout << fp[l] <<" " <<val[fp[l]]<<endl;
return;
}
build(lson,l,tree[i].mid);
build(rson,tree[i].mid+1,r);
} void update(int i,int k,int val)
{
if(tree[i].l == k && tree[i].r == k)
{
// cout << fp[k] <<" " <<val<<endl;
tree[i].Min = val;
return;
}
int mid = tree[i].mid;
if(k <= mid) update(lson,k,val);
else update(rson,k,val);
push_up(i);
// cout << tree[i].l <<" " <<tree[i].r <<" " <<tree[i].Min<<endl;
}
ll query(int i,int l,int r)
{
// cout <<"l:"<< l <<" r:"<<r <<" min:"<< tree[i].Min<<endl;
if(tree[i].l >= l && tree[i].r <= r)
return tree[i].Min;
int mid = tree[i].mid;
if(r <= mid)
return query(lson,l,r);
else if(l > mid)
return query(rson,l,r);
else
{
return query(lson,l,mid)^query(rson,mid+1,r);
}
}
ll fin(int u,int v)
{
int f1 = top[u],f2 = top[v];
ll tmp = 0;
// cout <<u <<" " <<v <<endl;
// cout <<f1 <<" " <<f2 <<endl;
while(f1 != f2)
{
if(dep[f1] < dep[f2])
{
swap(f1,f2),swap(u,v);
}
tmp = tmp^query(1,p[f1],p[u]);
u = fa[f1],f1 = top[u];
}
if(u == v) return tmp;
if(dep[u] > dep[v]) swap(u,v);
// cout << son[u] << " " <<v <<endl;
return (tmp^query(1,p[u],p[v]));
} //int a[maxn]; int main()
{
// freopen("in.txt","r",stdin);
int T,cas = 1,op;
int a,b;
int m,u,v;
scanf("%d",&T);
while(T--)
{
ini();
scanf("%d%d",&n,&m);
for(int i =1;i <n;i++)
{
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
dfs1(1,0,0);
getpos(1,1);
build(1,1,pos-1);
for(int i =1;i <= n;i++)
{
scanf("%d",&a);
update(1,p[i],a+1);
}
for(int i = 1;i <= m;i++)
{
scanf("%d%d%d",&op,&a,&b);
if(op == 0)
{
update(1,p[a],b+1);
}
else
{
int t = fin(a,b);
// cout<<"t:"<<t<<endl;
if(!t)
printf("-1\n");
else
printf("%d\n",t-1);
}
}
}
return 0;
}
hdu 5274 树链剖分的更多相关文章
- HDU 5274(树链剖分)
树链剖分第一题QAQ,纪念下 #pragma comment(linker, "/STACK:102400000,102400000") #include <iostream ...
- hdu 5893 (树链剖分+合并)
List wants to travel Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/O ...
- hdu 5052 树链剖分
Yaoge’s maximum profit Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/ ...
- hdu 4897 树链剖分(重轻链)
Little Devil I Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others ...
- HDU 3966 (树链剖分+线段树)
Problem Aragorn's Story (HDU 3966) 题目大意 给定一颗树,有点权. 要求支持两种操作,将一条路径上的所有点权值增加或减少ai,询问某点的权值. 解题分析 树链剖分模板 ...
- hdu 3966(树链剖分+线段树区间更新)
传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...
- HDU 3966 /// 树链剖分+树状数组
题意: http://acm.hdu.edu.cn/showproblem.php?pid=3966 给一棵树,并给定各个点权的值,然后有3种操作: I x y z : 把x到y的路径上的所有点权值加 ...
- hdu 4729 树链剖分
思路:这个树链剖分其实还是比较明显的.将边按权值排序后插入线段树,然后用线段树查找区间中比某个数小的数和,以及这样的数的个数.当A<=B时,就全部建新的管子. 对于A>B的情况比较 建一条 ...
- hdu 3966 树链剖分
思路:树链剖分入门题,我这门入得好苦啊,程序很快写出来了,可是在LCA过程中把update函数里的左右边界位置写反了,一直RE到死. #pragma comment(linker, "/ST ...
随机推荐
- 转git取消commit
如果不小心commit了一个不需要commit的文件,可以对其进行撤销. 先使用git log 查看 commit日志 commit 422bc088a7d6c5429f1d0760d008d8 ...
- 201621123068 作业07-Java GUI编程
1. 本周学习总结 1.1 思维导图:Java图形界面总结 2.书面作业 1. GUI中的事件处理 1.1 写出事件处理模型中最重要的几个关键词. 注册.事件.事件源.监听 1.2 任意编写事件处理相 ...
- 算法第四版 coursera公开课 普林斯顿算法 ⅠⅡ部分 Robert Sedgewick主讲《Algorithms》
这是我在网上找到的资源,下载之后上传到我的百度网盘了. 包含两部分:1:算法视频的种子 2:字幕 下载之后,请用迅雷播放器打开,因为迅雷可以直接在线搜索字幕. 如果以下链接失效,请在下边留言,我再更新 ...
- .net 小程序获取用户UnionID
第一次写博客,写的不好多多海涵! 1.小程序获取UnionID的流程用code去换取session_key,然后去解密小程序获取到的那串字符! 话不多说,原理大家都懂!!!!!! 直接上代码 publ ...
- recompose mapProps
mapProps介绍 mapProps函数接收一个函数参数,这个函数参数会返回一个对象用作为接下来的组件的props.组件接收到的props只能是通过mapProps函数参数返回的对象,其他的prop ...
- kubernetes入门(03)kubernetes的基本概念
一.Pod 在Kubernetes集群中,Pod是创建.部署和调度的基本单位.一个Pod代表着集群中运行的一个进程,它内部封装了一个或多个应用的容器.在同一个Pod内部,多个容器共享存储.网络IP,以 ...
- python入门(10)使用List和tuple
python入门(10)使用List和tuple list Python内置的一种数据类型是列表:list.list是一种有序的集合,可以随时添加和删除其中的元素. 比如,列出班里所有同学的名字,就可 ...
- Python之函数的进阶(带参数的装饰器)
函数篇--装饰器二 带参数的装饰器 def outer(flag): def timer(func): def inner(*args,**kwargs): if flag: print('''执行函 ...
- centos7 yum相关的常用命令
[root@mini1 ~]# history |grep yum 40 yum repolist 42 cd /etc/yum.repos.d/ 49 yum clean all 50 yum re ...
- jsp和servlet的区别和联系
jsp和servlet的区别和联系:1.jsp经编译后就变成了Servlet.(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器将JSP的代码编译成JVM能 ...