SPOJ - QTREE (树链剖分)

2024-06-24 06:48
文章标签 spoj qtree 树链 剖分

本文主要是介绍SPOJ - QTREE (树链剖分),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    基础的树链剖分题目,不过是边权,可以向下映射成点权或者按边剖分。

VIEW CODE

#include <iostream>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<algorithm>
#include<string>
using namespace std;
const int mmax=10010;
const int inf=0x3fffffff;
struct edge
{int st,en,cost;int next;
}E[2*mmax];
int p[mmax],fa[mmax],son[mmax],top[mmax],ID[mmax];
int deep[mmax],cost[mmax],id_[mmax];
bool vis[mmax];
int num;
void add(int st,int en,int cost)
{E[num].st=st;E[num].en=en;E[num].cost=cost;E[num].next=p[st];p[st]=num++;
}
void init()
{memset(p,-1,sizeof p);num=0;
}
struct tree
{int l,r;int max_n;int mid(){return (l+r)>>1;}
}T[4*mmax];
void build(int id,int l,int r)
{T[id].l=l,T[id].r=r;if(l==r){T[id].max_n=cost[ID[l]];return ;}int mid=T[id].mid();build(id<<1,l,mid);build(id<<1|1,mid+1,r);T[id].max_n=max(T[id<<1].max_n,T[id<<1|1].max_n);
}
void updata(int id,int pos,int val)
{if(T[id].l==T[id].r){T[id].max_n=val;return ;}int mid=T[id].mid();if(mid>=pos)updata(id<<1,pos,val);elseupdata(id<<1|1,pos,val);T[id].max_n=max(T[id<<1].max_n,T[id<<1|1].max_n);
}
int query(int id,int l,int r)
{if(l<=T[id].l&&T[id].r<=r)return T[id].max_n;int mid=T[id].mid();int ans=0;if(mid>=l)ans=max(ans,query(id<<1,l,r));if(mid<r)ans=max(ans,query(id<<1|1,l,r));return ans;
}
int dfs(int u)
{vis[u]=1;int cnt=1,tmp=0,e=0,Co=inf;for(int i=p[u];i+1;i=E[i].next){int v=E[i].en;int len=E[i].cost;if(!vis[v]){fa[v]=u;deep[v]=deep[u]+1;cost[v]=len;int tt=dfs(v);cnt+=tt;if(tmp<tt){tmp=tt;e=v;Co=len;}}}son[u]=e;return cnt;
}
int now_cnt;
void new_id(int u)
{ID[now_cnt]=u;id_[u]=now_cnt;now_cnt++;vis[u]=1;if(son[u]){top[son[u]]=top[u];new_id(son[u]);}for(int i=p[u];i+1;i=E[i].next){int v=E[i].en;if(!vis[v])new_id(v);}
}
int solve(int x,int y)
{int ans=0;while(top[x]!=top[y]){if(deep[top[x]]<deep[top[y]])swap(x,y);ans=max(ans,query(1,id_[top[x]],id_[x]));x=fa[top[x]];}if(x!=y){if(deep[x]>deep[y])swap(x,y);ans=max(ans,query(1,id_[son[x]],id_[y]));}return ans;
}
char str[20];
int main()
{int t,n;scanf("%d",&t);while(t--){init();scanf("%d",&n);for(int i=0;i<n-1;i++){int u,v,cost;scanf("%d %d %d",&u,&v,&cost);add(u,v,cost);add(v,u,cost);}fa[1]=1;deep[1]=0;cost[1]=0;memset(vis,0,sizeof vis);for(int i=1;i<=n;i++)top[i]=i;dfs(1);memset(vis,0,sizeof vis);now_cnt=1;new_id(1);
//        for(int i=1;i<=n;i++)
//            cout<<son[i]<<" ";
//        cout<<endl;
//        system("pause");build(1,1,n);while(1){int a,b;scanf("%s",str);if(!strcmp(str,"DONE"))break;scanf("%d %d",&a,&b);if(!strcmp(str,"QUERY"))printf("%d\n",solve(a,b));if(!strcmp(str,"CHANGE")){int st=E[2*a-2].st;int en=E[2*a-2].en;if(deep[st]>deep[en])swap(st,en);updata(1,id_[en],b);}}//system("pause");}return 0;
}


这篇关于SPOJ - QTREE (树链剖分)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1089461

相关文章

[HDU 5029] Relief grain (树链剖分+线段树)

HDU - 5029 其实这道题最大的难点不是树链剖分,而是怎么维护某个点被那些颜色染过,染过多少次 如果在线段树维护的话,很难做到,估计得树套树,而且空间会炸 好在这题是离线的,可以使用差分的思想来维护 对一段区间[l,r]染色 c,相当于在这段区间左端点 l打上 c标志,右端点 r+1打上 -c标志 然后扫一遍整个区间 (依照 dfs序扫一遍整棵树),期间不断维护一颗线段树 线段树

计算几何【三角剖分】

在几何中,三角剖分是指将平面对象细分为三角形,并且通过扩展将高维几何对象细分为单纯形。 对于一个给定的点集,有很多种三角剖分,如: OI 中的三角剖分主要指二维几何中的完美三角剖分(二维 Delaunay 三角剖分,简称 DT)。 Delaunay 三角剖分 定义 在数学和计算几何中,对于给定的平面中的离散点集 P P P,其 Delaunay 三角剖分 DT( P P P) 满足:

HDU 3966 Aragorn's Story 树链剖分

入门题 #include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 50010;struct edge{int v, next;}e[maxn*2];int n, m, q;int first[maxn], cnt;int top[maxn], tid[

poj3237 Tree 树链剖分

题意:在spoj375基础上增加了一条路径的取反操作,其他都一样。 思路:剖分没有变化,在线段树部分,需要一个tag标记该段是否需要需要取反,记录一个最大值、最小值即可。=  =(打tag的那 段应该已经跟新好,push_down的时候如果tag=1那么直接对两个子段进行更新。。一开始意识模糊了。。)详见代码: /************************************

fzu2082 过路费 树链剖分

题意:中文题。。 思路:树链剖分后,在线段树上单点更新,区间查询。详见代码: /*********************************************************file name: fzu2082.cppauthor : kereocreate time: 2015年01月21日 星期三 09时21分42秒***********************

树链剖分 更新中

首先贴一个别人的动态开点模板 树链剖分详解 #include<iostream>#include<cstdio>using namespace std;const int maxn=1e5+10;struct edge{int next,to;}e[2*maxn];struct Node{int sum,lazy,l,r,ls,rs;}node[2*maxn];int rt,

spoj 227

留着 #include <cstdio>#include <cstring>#include <cstdlib>#define lson l, m, rt << 1#define rson m + 1, r, rt << 1 | 1const int MAXN = 200010;int pos[MAXN];int sum[MAXN << 2];// = MAXN*4int ans[

spoj 416

又臭又长的烂代码 ...... #include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#define maxn 1010using namespace std;char a[1010];int num[10],last;//bool cc(int sum)

spoj 1108

要求输出一个牌的顺序 使每隔1、2、.....、n翻牌后出现1 2 3 4 5 6 7 8 9 .... n 将牌想象成n个空格  正向推 空n个位置放n 循环 需优化 #include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <cmath>#define maxn 300

spoj 379

题是水题  但丫的题目意思太难懂 .......   英语水平  ...... #include <cstdio>#include <cstring>#include <vector>#include <queue>using namespace std;int a[100010];int main(){int n;while(scanf("%d",&n) && n){for(i