HYSBZ 1036 树的统计Count

原创 2015年11月19日 15:07:14

树链剖分看了半个星期,感觉自己可以上题了

轻重链划分倒是一下就看懂了,两遍dfs的剖分应该都卡不住(刚开始以为是子树中最深的那个为重链的我也是图样)(其实是子树结点更多的那个)

但是卡在了树上的查询上,怎么也理解不了怎么做到不重不漏,感觉总是有一个迷の情况会多询问一个节点或少询问一个节点

终于有一天感觉自己不能这样想下去了(然后拿出了草稿纸),在纸上自己推了一发,然后发现了树剖的循环不变式!(大雾

就是每次从链顶到链顶的父亲的时候,链顶的父亲总是没有被更新的,(如果用灰色来表示未询问的点,黑色表示已经查询过了的点,那么每次走上来的时候所站的地方都是灰色的点,也就是说,和刚开始的情况是一样一样的

然后就木有了。。。。

至少对我来说树剖只有这个地方卡了我一下

感觉kuangbin大神的一句话说的很好,树剖只是一些区间算法在树上的应用罢了


这个题也是很裸的模板,区间和还有区间最值的查询在线段树上也是挺裸的东西,就不细说了


以及代码


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

const int INF = 0x3f3f3f3f;
const int maxn = 112345;

vector<int> edge[maxn];

void init(int n){
	for(int i=0;i<=n;i++)
		edge[i].resize(0);
}

void Link(int st,int ed){
	edge[st].push_back(ed);
	edge[ed].push_back(st);
}

struct Info{
	int m,s;
	Info(){
		m=-INF,s=0;
	}
	void out(){
		printf("max = %lld sum = %lld\n",m,s);
	}
};

#define debug123

Info operator + (const Info &a,Info b){
	b.s+=a.s;
	b.m=max(b.m,a.m);
	return b;
}

Info val[maxn*4];
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define root 1,1,n
#define Now int o,int l,int r
#define Mid int m = l + (r-l)/2

void update(Now,int up,int uv){
	if(l==r){
		val[o].m=val[o].s=uv;
		return;
	}
	Mid;
	if(up<=m)
		update(lson,up,uv);
	else
		update(rson,up,uv);
	val[o]=val[o<<1]+val[o<<1|1];
}

Info query(Now,int ql,int qr){
	if(ql<=l && r<=qr){
		return val[o];
	}
	Info ret;
	Mid;
	if(ql<=m)
		ret = ret+query(lson,ql,qr);
	if(m+1<=qr)
		ret = ret+query(rson,ql,qr);
	return ret;
}

int son[maxn],fa[maxn],top[maxn],sid[maxn],siz[maxn],deep[maxn];
int _cnt;

void dffs(int st,int Fa,int Deep){
	deep[st]=Deep,fa[st]=Fa,siz[st]=1;
	for(vector<int>::iterator it = edge[st].begin();it!=edge[st].end();it++){
		int x = *it;
		if(x!=Fa){
			dffs(x,st,Deep+1);
			siz[st]+=siz[x];
			if(son[st]==-1 || siz[son[st]] < siz[x]){
				son[st]=x;
			}
		}
	}
}

void dfss(int st,int tp){
	top[st]=tp,sid[st]=_cnt++;
	if(son[st]!=-1)
		dfss(son[st],tp);
	for(vector<int>::iterator it = edge[st].begin();it!=edge[st].end();it++){
		int x = *it;
		if(x!=fa[st] && x!=son[st]){
			dfss(x,x);
		}
	}
}

void splite(){
	memset(son,-1,sizeof(son));
	_cnt=1;
	dffs(1,0,1);
	dfss(1,1);
}

void upd(int p,int v,int n){
	update(root,sid[p],v);
}

Info que(int x,int y,int n){
	Info ret;
	int tx = top[x];
	int ty = top[y];
	while(tx!=ty){
		if(deep[tx] > deep[ty]){ //up x
			ret = ret + query(root,sid[tx],sid[x]);
			x = fa[tx],tx = top[x];
		}
		else{
			ret = ret + query(root,sid[ty],sid[y]);
			y = fa[ty],ty = top[y];
		}
                    #ifdef debug
                            ret.out();
                    #endif
	}
	if(deep[x] > deep[y]){
		ret = ret + query(root,sid[y],sid[x]);
	}
	else{
		ret = ret + query(root,sid[x],sid[y]);
	}
                    #ifdef debug
                        printf("after x = %d y = %d\n",x,y);
                        ret.out();
                    #endif
	return ret;
}

#ifdef debug
void out(char *nam,int *s,int n){
	puts(nam);
	for(int i=1;i<=n;i++)
		printf(i<n?"%d ":"%d\n",s[i]);
}
#endif

int main(){
	int n,m;
	char ord[20];
	scanf("%d",&n);
	init(n);
	int x,y;
	for(int i=1;i<n;i++){
		scanf("%d %d",&x,&y);
		Link(x,y);
	}
	splite();
#ifdef debug
	out("fa",fa,n);
	out("son",son,n);
	out("top",top,n);
	out("deep",deep,n);
#endif
	for(int i=1;i<=n;i++){
		scanf("%d",&x);
		upd(i,x,n);
	}
	scanf("%d\n",&m);
	while(m--){
		scanf("%s",ord);
		scanf("%d %d",&x,&y);
		if(ord[0]=='Q'){
			Info ans = que(x,y,n);
			if(ord[1]=='M')
				printf("%d\n",ans.m);
			else
				printf("%d\n",ans.s);
		}
		else{
			upd(x,y,n);
		}
	}
	return 0;
}
/*
10
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
1 1 1 1 1 1 1 1 1 1
10086
QMAX 1 3
QMAX 1 10
QSUM 3 4
CHANGE 3 6
QMAX 1 3
QMAX 1 10
QSUM 3 4


7
1 2
2 3
3 4
1 5
5 6
6 7
1 1 1 1 1 1 1
10086
QSUM 4 7
QMAX 4 7
QSUM 2 6
CHANGE 1 12
QSUM 4 7
QMAX 4 7
QSUM 2 6
CHANGE 7 10086
QSUM 4 7
QMAX 4 7
QSUM 2 6
*/


版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

HYSBZ 1036 树链剖分(单点更新区间求和求最大值)

http://www.lydsy.com/JudgeOnline/problem.php?id=1036 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值...

HYSBZ 1036 树的统计Count(树链剖分)

HYSBZ 1036 树的统计Count 题目链接 就树链剖分,线段树维护sum和maxx即可 代码: #include #include #include #inclu...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

poj1236 - Network of Schools

想看更多的解题报告: http://blog.csdn.net/wangjian8006/article/details/7870410              &...

HDU 3605 Escape

题意:有n个人要移居m个星球,给出每个合适的星球,每个星球最多能容纳的人数,问是否所有人都可以移居。(1≤N≤105,1≤M≤10)  很明显这里的边有超过1e6条,所以我能直接跑,然后你会发现...

HDU - 4685 Prince and Princess

There are n princes and m princesses. Princess can marry any prince. But prince can only marry the p...

Rman switch to copy

With RMAN you can create copy of live Database and perform the switch to copy when main database is ...

poj1236 强连通分量——缩点

【题意】 N(2 【题解】 找强连通分量,缩点。记f[i]为缩完点后的新图中各点入度,g[i]为出度,ans1为f[i]==0的点的数目,ans2为g[i]==0的点的数目则第一问为ans1...

poj1236-Tarjan算法

poj1236--Tarjan算法 题目大意:     一些学校连成了网络, 在学校之间存在某个协议:每个学校都维护一张传送表,表明他们要负责将收到的软件传送到表中的所有学校。如果A在B的表中,那...

FZU - 2082 过路费

树剖的裸题,中文题面所以就不多解释了,当然操作二,就是简单的求过路费之和,因为路径唯一,他的那个最少过路费我也是醉了。 #include #include #include #include ...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)