您的位置:首页 > 产品设计 > UI/UE

SPOJ QTREE Query on a tree

2015-06-04 22:12 423 查看
树链剖分

把边权的模板也敲了一下

关键在于弄明白点和边的对应关系

#include<stdio.h>
#include<string.h>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<math.h>
using namespace std;
#define out(x) cout<<#x<<": "<<x<<endl
const double eps(1e-8);
const int maxn=10100;
const long long inf=-1u>>1;
typedef long long ll;
int n,e[maxn][3],tot,pos;
int deep[maxn],fa[maxn],num[maxn],son[maxn];
int top[maxn],p[maxn],fp[maxn];
struct Edge{
int v,next;
}edge[maxn<<1];
int head[maxn];
void addedge(int u,int v){
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
}
void dfs1(int u,int pre,int d){//求fa、num、son和deep
deep[u]=d;
fa[u]=pre;
num[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==pre) continue;
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){//sp用于求top,并求对应位置
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!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==fa[u]||v==son[u]) continue;
getpos(v,v);
}
}
struct Node{
int l,r,max;
}t[maxn<<2];
void build(int p,int l,int r){
t[p].l=l;
t[p].r=r;
t[p].max=0;
if(l==r) return;
int mid=(l+r)>>1;
build(p<<1,l,mid);
build((p<<1)|1,mid+1,r);
}
void update(int p,int k,int val){
if(t[p].l==k&&k==t[p].r) {
t[p].max=val;
return;
}
int mid=(t[p].l+t[p].r)>>1;
if(k<=mid) update(p<<1,k,val);
else update((p<<1)|1,k,val);
t[p].max=max(t[p<<1].max,t[(p<<1)|1].max);
}
int query(int p,int l,int r){
if(t[p].l==l&&t[p].r==r){
return t[p].max;
}
int mid=(t[p].l+t[p].r)>>1;
if(r<=mid) return query(p*2,l,r);
else if(l>mid) return query(p*2+1,l,r);
else return max(query(p*2,l,mid),query(p*2+1,mid+1,r));
}
void init() {
tot=0;
pos=0;
memset(son,-1,sizeof(son));
memset(head,-1,sizeof(head));
scanf("%d",&n);
for(int i=0;i<n-1;i++){
scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
addedge(e[i][0],e[i][1]);
addedge(e[i][1],e[i][0]);
}
dfs1(1,0,0);
getpos(1,1);
build(1,0,pos-1);
}

int find(int u,int v){
int f1=top[u],f2=top[v];
int tmp=0;
while(f1!=f2){
if(deep[f1]<deep[f2]) {
swap(f1,f2);
swap(u,v);
}
tmp=max(tmp,query(1,p[f1],p[u]));
u=fa[f1];f1=top[u];//这里直接令u=fa[f1],所以上面查询最大值的时候可以直接用p[f1]
}
if(u==v) return tmp;
if(deep[u]>deep[v]) swap(u,v);
return max(tmp,query(1,p[son[u]],p[v]));//对每个节点来说,儿子可能有多个,但父结点只有一个,所以用一条边的下方的结点表示该边
}
int main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt","r",stdin);
#endif
int T;
scanf("%d",&T);
while(T--){
init();
for(int i=0;i<n-1;i++){
if(deep[e[i][0]]>deep[e[i][1]]) swap(e[i][0],e[i][1]);
update(1,p[e[i][1]],e[i][2]);
}
char op[10];
int a,b;
while(scanf("%s",op)==1){
if(op[0]=='D') break;
scanf("%d%d",&a,&b);
if(op[0]=='Q'){
printf("%d\n",find(a,b));
}
else update(1,p[e[a-1][1]],b);//编号从0开始

}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: