• bzoj 3221: Obserbing the tree树上询问 树链剖分+线段树


    题目大意:

    http://www.lydsy.com/JudgeOnline/problem.php?id=3221

    题解

    啊呀。。。这是昨天的考试题啊。。。直接就粘了。。
    4515: [Sdoi2016]游戏类似,还更简单了一些。
    (考场上因为没开long long爆了25分)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(ll &x){
    	x=0;char ch;bool flag = false;
    	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    const ll maxn = 100010;
    struct Edge{
    	ll to,next;
    }G[maxn<<1];
    ll head[maxn],cnt;
    void add(ll u,ll v){
    	G[++cnt].to = v;
    	G[cnt].next = head[u];
    	head[u] = cnt;
    }
    #define v G[i].to
    ll fa[maxn],dfn[maxn],top[maxn],dep[maxn],siz[maxn];
    ll son[maxn],dfs_clock,seq[maxn],sum[maxn];
    void dfs(ll u){
    	siz[u] = 1;
    	for(ll i = head[u];i;i=G[i].next){
    		if(v == fa[u]) continue;
    		fa[v] = u;
    		dep[v] = dep[u] + 1;
    		dfs(v);
    		siz[u] += siz[v];
    		if(siz[son[u]] < siz[v]) son[u] = v;
    	}
    }
    void dfs(ll u,ll tp){
    	top[u] = tp;dfn[u] = ++dfs_clock;
    	seq[dfs_clock] = u;
    	if(son[u]) dfs(son[u],tp);
    	for(ll i = head[u];i;i=G[i].next){
    		if(v == son[u] || v == fa[u]) continue;
    		dfs(v,v);
    	}
    }
    #undef v
    inline ll lca(ll u,ll v){
    	while(top[u] != top[v]){
    		if(dep[top[u]] < dep[top[v]]) swap(u,v);
    		u = fa[top[u]];
    	}return dep[u] < dep[v] ? u : v;
    }
    
    struct Node{
    	Node *ch[2];
    	ll sum,k,b;
    	ll dep_sum;
    	void update(){
    		dep_sum = ch[0]->dep_sum + ch[1]->dep_sum;
    		sum = ch[0]->sum + ch[1]->sum;
    	}
    }*null,*root[maxn],*rt;
    Node mem[25001001],*it;
    inline void init(){
    	it = mem;
    	null = it++;null->ch[0] = null->ch[1] = null;
    	null->sum = null->k = null->b = 0;null->dep_sum = 0;
    	root[0] = null;
    }
    inline Node *newNode(){
    	Node *p = it++;p->ch[0] = p->ch[1] = null;
    	p->sum = p->k = p->b = p->dep_sum = 0;
    	return p;
    }
    ll L,R,K,B,n,T;
    Node *change(Node *rt,ll l,ll r){
    	Node *p = newNode();*p = *rt;
    	if(L <= l && r <= R){
    		p->k += K;p->b += B;
    		p->sum += K*p->dep_sum + B*(r-l+1);
    		return p;
    	}ll mid = (l+r) >> 1;
    	if(L <= mid) p->ch[0] = change(p->ch[0],l,mid);
    	if(R >  mid) p->ch[1] = change(p->ch[1],mid+1,r);
    	p->update();p->sum += p->dep_sum*p->k + (r-l+1)*p->b;
    	return p;
    }
    void change(ll u,ll v,ll a,ll b){
    	ll lc = lca(u,v);
    	K = -b;B = (a+dep[u]*b);
    	while(top[u] != top[lc]){
    		L = dfn[top[u]];R = dfn[u];
    		rt = change(rt,1,n);
    		u = fa[top[u]];
    	}
    	L = dfn[lc];R = dfn[u];
    	rt = change(rt,1,n);
    	K = b;B -= 2*dep[lc]*b;
    	while(top[v] != top[lc]){
    		L = dfn[top[v]];R = dfn[v];
    		rt = change(rt,1,n);
    		v = fa[top[v]];
    	}
    	L = dfn[lc];R = dfn[v];
    	if(L == R) return;++L;
    	rt = change(rt,1,n);
    }
    ll query(Node *p,ll l,ll r,ll L,ll R){
    	if(L <= l && r <= R){
    		return p->sum;
    	}
    	ll ret = (sum[min(r,R)] - sum[max(l,L)-1])*p->k + p->b*(min(r,R) - max(l,L) + 1);
    	ll mid = (l+r) >> 1;
    	if(L <= mid) ret += query(p->ch[0],l,mid,L,R);
    	if(R >  mid) ret += query(p->ch[1],mid+1,r,L,R);
    	return ret;
    }
    inline ll query(ll u,ll v){
    	ll ret = 0;
    	while(top[u] != top[v]){
    		if(dep[top[u]] < dep[top[v]]) swap(u,v);
    		ret += query(rt,1,n,dfn[top[u]],dfn[u]);
    		u = fa[top[u]];
    	}if(dep[u] > dep[v]) swap(u,v);
    	ret += query(rt,1,n,dfn[u],dfn[v]);
    	return ret;
    }
    Node *build(ll l,ll r){
    	Node *p = newNode();
    	if(l == r){
    		p->dep_sum = dep[seq[l]];
    		p->sum = 0;
    		return p;
    	}
    	ll mid = (l+r) >> 1;
    	p->ch[0] = build(l,mid);
    	p->ch[1] = build(mid+1,r);
    	p->update();return p;
    }
    char s[10];
    int main(){
    	init();
    	ll last = 0,total = 0;
    	ll m;read(n);read(m);
    	for(ll i=1,u,v;i<n;++i){
    		read(u);read(v);
    		add(u,v);add(v,u);
    	}dfs(1);dfs(1,1);root[0] = build(1,n);
    	sum[0] = 0;
    	for(ll i=1;i<=n;++i) sum[i] = sum[i-1] + dep[seq[i]];
    	rt = root[0];
    	ll u,v,a,b,w;
    	while(m--){
    		scanf("%s",s);
    		if(*s == 'c'){
    			read(u);read(v);read(a);read(b);
    			u ^= last;v ^= last;
    			change(u,v,a,b);
    			root[++total] = rt;
    		}else if(*s == 'q'){
    			read(u);read(v);
    			u ^= last;v ^= last;
    			printf("%lld
    ",last = query(u,v));
    		}else{
    			read(w);w ^= last;
    			rt = root[w];
    		}
    	}
    	getchar();getchar();
    	return 0;
    }
    
  • 相关阅读:
    将不确定变成确定~LINQ DBML模型可以对应多个数据库吗
    将不确定变成确定~frameset页面不能正确加载
    System.Web.Caching.Cache删除某键后,希望同时触发其它动作(关键时刻,还是事件靠的住)
    Linq实体类的设计(解决了复合查询的问题,同时解决了LINQ上下文缓存问题)
    将不确定变成确定~LINQ查询两种写法,性能没有影响,优化查询应该是“按需查询”
    ASP.NET的内置对象
    Templating with JSF 2.0 Facelets
    IOS设计模式学习(1)设计模式初窥
    20个强大的jQuery翻书插件【 jQuery flipbook】
    linux网络编程之socket(十四):基于UDP协议的网络程序
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6446003.html
Copyright © 2020-2023  润新知