【spoj375】Query on a tree【树链剖分】【或者动态树,那样常数就完了T_T】
来源:互联网 发布:淘宝偷图技巧 编辑:程序博客网 时间:2024/05/23 10:22
hahahaha!
今天(3月12)我终于ac了……
orz Yan Big God!
他问我能不能
并且提供了一个“反映射“的思想。
我想我们连反映射都可以不要……
鉴于ZKW的特殊性……
我们只要
for(int i=1;i<n;++i){ if(dep[d[i][0]]<dep[d[i][1]]) swap(d[i][0],d[i][1]); t[w[d[i][0]]+M]=d[i][2]; }//w是树上节点到线段树的映射,M是ZKW线段树的偏移量 for(int i=M-1;i;--i) t[i]=max(t[i<<1],t[i<<1|1]);
这样可以使
【这道题貌似用LCT也能A,不过splay常数大的要死(0.63,树剖0.23)- -我还以为我要T了呢- -】
#include<cstdio>#include<cstring>#include<iostream>using namespace std;const int maxn=30001;typedef int arr[maxn<<1];typedef int arr1[maxn];int M,t[65536];arr next,to;arr1 list,fa,dep,size,son,top,w;int rt,n,tot,ttot,z,d[maxn][3];inline void add(int a,int b){ ++tot; next[tot]=list[a]; list[a]=tot; to[tot]=b; ++tot; next[tot]=list[b]; list[b]=tot; to[tot]=a;}bool visit[20000];void dfs(int v){ size[v]=1;son[v]=0; for(int k=list[v];k;k=next[k]) if(to[k]!=fa[v]){ fa[to[k]]=v; dep[to[k]]=dep[v]+1; dfs(to[k]); size[v]+=size[to[k]]; if(size[to[k]]>size[son[v]]) son[v]=to[k]; }}void buildtree(int v,int tp){ w[v]=++z;top[v]=tp; if(son[v]) buildtree(son[v],top[v]); for(int k=list[v];k;k=next[k]) if(to[k]!=fa[v]&&to[k]!=son[v]) buildtree(to[k],to[k]);}inline void change(int p,int x){ for(t[p+=M]=x,p>>=1;p;p>>=1) t[p]=max(t[p<<1],t[p<<1|1]);}int query(int L,int R){ int ans=1<<31; for(L+=M-1,R+=M+1;L^R^1;L>>=1,R>>=1){ if(~L&1) ans=max(ans,t[L^1]); if( R&1) ans=max(ans,t[R^1]); } return ans;}inline int find(int va,int vb){ int f1=top[va],f2=top[vb],tmp=1<<31; while(f1!=f2){ if(dep[f1]<dep[f2]) swap(f1,f2),swap(va,vb); tmp=max(tmp,query(w[f1],w[va])); va=fa[f1];f1=top[va]; } if(va==vb)return tmp; if(dep[va]>dep[vb]) swap(va,vb); return max(tmp,query(w[son[va]],w[vb]));}inline int read(){ int x=0; char ch=getchar(); while(!isdigit(ch)){ch=getchar();} while(isdigit(ch)){x=x*10+ch-48;ch=getchar();} return x;}inline void init(){ n=read(); M=1; while(M<=n) M<<=1; memset(list,0,sizeof(int)*(n+1)); ttot=rt=z=0; tot=0; for(int i=1;i<n;++i){ d[i][0]=read(),d[i][1]=read(),d[i][2]=read(); add(d[i][0],d[i][1]); } dfs(1); buildtree(1,1); for(int i=1;i<n;++i){ if(dep[d[i][0]]<dep[d[i][1]]) swap(d[i][0],d[i][1]); t[w[d[i][0]]+M]=d[i][2]; } for(int i=M-1;i;--i) t[i]=max(t[i<<1],t[i<<1|1]);}int a[10];inline void print(int x){ if(x) a[0]=0; else a[1]=0,a[0]=1; while(x) a[++a[0]]=x%10,x/=10; for(;a[0];--a[0]) putchar(a[a[0]]+48); putchar('\n');}int main(){ char ch; int x,y,t; for(t=read();t;--t){ init(); while(1){ ch=getchar(); while(ch!='D'&&ch!='Q'&&ch!='C') ch=getchar(); if(ch=='D') break; if(ch=='Q') print(find(read(),read())); else{ x=read(),y=read(); change(w[d[x][0]],y); } } putchar('\n'); } return 0;}
这是LCT版的:(我旋转居然又写挂了- -)因为要把一条边也当做点来处理所以数组开大点- -
#include<cstdio>#include<cstring>#include<iostream>#define STOP do{puts("there");while(1);}while(0)using namespace std;const int maxn=90001;const int inf=1<<30;struct node{ node *f,*ch[2]; int v,s,maxi;bool p,flip; inline bool isRoot(); inline void rev(){flip^=1;} inline void upd(){ s=ch[0]->s+ch[1]->s+1; maxi=max(v,max(ch[0]->maxi,ch[1]->maxi)); }}t[maxn],*stack[maxn],*cur=t;int n;inline bool node::isRoot(){return f==t||this!=f->ch[p];}inline node *NewNode(node *f=t,int v=-inf){ ++cur; cur->f=f; cur->ch[0]=cur->ch[1]=t; cur->s=1; cur->v=v; cur->flip=false; cur->maxi=v; return cur;}inline void sc(node *a,node *b,bool c){ a->ch[c]=b;b->f=a;b->p=c;}inline void pushdown(node *x){ if(x->flip){//其实if(x->ch[0]!=t)不必判断的 if(x->ch[0]!=t) x->ch[0]->p^=1,x->ch[0]->flip^=1; if(x->ch[1]!=t) x->ch[1]->p^=1,x->ch[1]->flip^=1; swap(x->ch[0],x->ch[1]); x->flip=0;//!!!!!!!!! }}inline void rot(node *x){ node *y=x->f;bool p=x->p; if(y->isRoot()) x->f=y->f; else sc(y->f,x,y->p); sc(y,x->ch[!p],p); sc(x,y,!p); y->upd();}inline void splay(node *x){ int top;stack[top=1]=x; for(node *p=x;!p->isRoot();p=p->f) stack[++top]=p->f; while(top) pushdown(stack[top--]); while(!x->isRoot()){ if(x->f->isRoot()) rot(x); else if(x->f->p==x->p) rot(x->f),rot(x); else rot(x),rot(x);// cout<<"锕"; }//cout<<"铪\n"; x->upd();}inline void splice(node *x){splay(x->f);sc(x->f,x,1);x->f->upd();splay(x);}inline void expose(node *x){splay(x);while(x->f!=t) splice(x);}inline void reroot(node *x){expose(x);x->ch[1]=t;x->upd();x->rev();}inline void link(node *x,node *y){ expose(x); x->ch[0]=y;x->upd();}inline int query(node *x,node *y){ reroot(x);reroot(y); return y->maxi;}inline void change(node *x,int toWhat){ splay(x); x->v=toWhat; x->upd();}inline int read(){ int x=0; char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) x=x*10+ch-48,ch=getchar(); return x;}node *idx[maxn<<1];int tot,to[maxn<<1],next[maxn<<1],list[maxn],cost[maxn<<1];inline void add(int a,int b,int c){ next[++tot]=list[a]; list[a]=tot; to[tot]=b; cost[tot]=c;}int q[maxn];node *fa[maxn];inline void bfs(){ int head=0,tail=1,h; q[1]=1; fa[1]=t; while(head<tail){ h=q[++head]; idx[h]=NewNode(fa[h]?fa[h]:t); for(int k=list[h];k;k=next[k]) if(!idx[to[k]]){ idx[(k+1>>1)+n]=NewNode(idx[h],cost[k]); fa[to[k]]=idx[(k+1>>1)+n]; q[++tail]=to[k]; } }}inline void dfs(int x,node *f=t){ idx[x]=NewNode(f);}#define CLR(x) memset(x,0,sizeof x)inline void init(){ memset(idx,0,sizeof(node*)*(cur-t+1)); memset(list,0,sizeof(int)*(n+1)); tot=0; cur=t; t[0].maxi=1<<31; t[0].f=t; t[0].ch[0]=t[0].ch[1]=t;}int main(){ int T=read(),a,b,c; char cmd[10]; while(T--){ init(); n=read(); for(int i=1;i<n;++i){ a=read(),b=read();c=read(); add(a,b,c);add(b,a,c); } bfs(); for(;;){ scanf("%s",cmd); if(cmd[0]=='D') break; else if(cmd[0]=='Q'){ a=read();b=read(); printf("%d\n",query(idx[a],idx[b])); } else{ a=read();b=read(); change(idx[a+n],b); } } putchar('\n'); }}
0 0
- 【spoj375】Query on a tree【树链剖分】【或者动态树,那样常数就完了T_T】
- SPOJ375--Query on a tree(树链剖分)
- spoj375 Query on a tree 树链剖分
- spoj375 Query on a tree 树链剖分
- 【树链剖分】spoj375 Query on a tree
- kyeremal-spoj375-Query on a tree-树链剖分
- spoj375 Query on a tree(树链剖分)
- 【SPOJ375】Query on a tree-树链剖分
- 树链剖分+线段树 spoj375 Query on a tree
- [SPOJ375]Query on a tree
- SPOJ375 Query on a tree
- SPOJ375 Query on a tree
- spoj375 Query on a tree
- QTREE - Query on a tree 树链剖分 或者 动态树
- 【SPOJ375】 Query on a tree——树链剖分
- Spoj375 Query on a tree 裸·树链剖分
- SPOJ375 QTREE - Query on a tree
- Spoj375.Query on a tree——树链剖分+线段树(基于边权)
- CUDA: 使用shared memory
- poj3190
- 【蓝桥杯训练】------2n皇后问题
- 有没有办法获取最近操作的联系人
- Ubuntu 14.04 安装 Intel MKL + OpenCV
- 【spoj375】Query on a tree【树链剖分】【或者动态树,那样常数就完了T_T】
- C++省略号类型和参数个数不确定函数参数范例
- VC++动态链接库(DLL)编程深入浅出(zz)
- 反距离权重法生成DEM(利用KD-tree实现KNN算法)
- C#实现队列的基本操作
- 运用CXF-3.0.4中遇到的问题
- 序章
- Android 省市县 三级联动(android-wheel的使用)
- 尹老师视频代码(质数判断C语言)