2016ACM/ICPC Shengyang Online-1002 List wants to travel
来源:互联网 发布:淘宝信用查询网 编辑:程序博客网 时间:2024/05/01 03:20
题意:给定一棵n个节点的树,有两种询问:1.(a,b,c)把节点a到节点b上路径的权值改为c;2.(a,b)询问节点a到b路径上连续不同权值的个数(如1,2,3,3,1算4个)
题解:树链剖分+线段树统计区间权值的段数(好难想)
对于剖分后权值个数的统计,需要考虑区间连接处的权值。操作:对于点u,可以每次记录u的儿子到u那条边的权值(没有儿子则为-1),线段树取区间时同时记录区间两端点的权值大小,比较,相同则答案-1,不同则答案不变。
#include <iostream>#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <algorithm>#include <vector>using namespace std;const int N=40000+10;const int E=100000+10;int d[N],Fa[N],Size[N],Son[N],p[N],Top[N],pos;struct Node{ int cl,cr,m;}T[N<<2];int cL,cR;int n,m;int Edge[N][3],vp[N];vector<int>V[N],W[N];void dfs1(int u,int Pre,int Dep){ d[u]=Dep+1; Fa[u]=Pre; Size[u]=1; for (int i=0;i<int(V[u].size());i++){ int v=V[u][i]; if (v!=Pre){ dfs1(v,u,Dep+1); Size[u]+=Size[v]; if (Son[u]==-1 || Size[Son[u]]<Size[v])Son[u]=v; } }}void dfs2(int u,int sp){ Top[u]=sp; pos++;p[u]=pos; if (Son[u]==-1)return ; dfs2(Son[u],sp); for (int i=0;i<int(V[u].size());i++){ int v=V[u][i]; if (Fa[u]!=v && Son[u]!=v)dfs2(v,v); }}void Push_down(int p,int L,int R){ if (T[p].m==1){ T[p+p].cl=T[p+p+1].cl=T[p].cl; T[p+p].cr=T[p+p+1].cr=T[p].cr; T[p+p].m=T[p+p+1].m=T[p].m; }}void Push_up(int p,int L,int R){ T[p].cl=T[p+p].cl;T[p].cr=T[p+p+1].cr; T[p].m=T[p+p].m+T[p+p+1].m; if (T[p+p].cr==T[p+p+1].cl)T[p].m--;}void Build(int p,int L,int R){ if (L==R){ T[p].cl=vp[L]; T[p].cr=vp[L]; T[p].m=1; return ; } int mid=(L+R)>>1; Build(p+p,L,mid); Build(p+p+1,mid+1,R); Push_up(p,L,R);}int Find(int p,int L,int R,int l,int r,int gdl,int gdr){ if (L==gdl)cL=T[p].cl; if (R==gdr)cR=T[p].cr; if (L==l && R==r)return T[p].m; Push_down(p,L,R); int mid=(L+R)>>1; if (r<=mid)return Find(p+p,L,mid,l,r,gdl,gdr);else if (mid< l)return Find(p+p+1,mid+1,R,l,r,gdl,gdr);else{ int t1=Find(p+p,L,mid,l,mid,gdl,gdr)+Find(p+p+1,mid+1,R,mid+1,r,gdl,gdr); if (T[p+p].cr==T[p+p+1].cl)t1--; return t1; } Push_up(p,L,R);}int Query(int u,int v){ int Res=0; int f1=Top[u],f2=Top[v]; int pre1=-1,pre2=-1; while (f1!=f2){ if (d[f1]<d[f2]){ swap(pre1,pre2);swap(f1,f2);swap(u,v); } Res+=Find(1,1,pos,p[f1],p[u],p[f1],p[u]);//x相同的边 if (pre1==cR)Res--; pre1=cL;u=Fa[f1];f1=Top[u]; } if (u==v){ if (pre1!=-1 && pre1==pre2)Res--; return Res; } if (d[u]<d[v])swap(u,v),swap(pre1,pre2); Res+=Find(1,1,pos,p[Son[v]],p[u],p[Son[v]],p[u]);//相同的边 if (pre1!=-1 && pre1==cR)Res--; if (pre2!=-1 && pre2==cL)Res--; return Res;}void Insert(int p,int L,int R,int l,int r,int v){ if (L==l && R==r){ T[p].cl=T[p].cr=v;T[p].m=1; return ; } Push_down(p,L,R); int mid=(L+R)>>1; if (r<=mid)Insert(p+p,L,mid,l,r,v);else if (mid< l)Insert(p+p+1,mid+1,R,l,r,v);else{ Insert(p+p,L,mid,l,mid,v); Insert(p+p+1,mid+1,R,mid+1,r,v); } Push_up(p,L,R);}void Change(int u,int v,int w){ int f1=Top[u],f2=Top[v]; while (f1!=f2){ if (d[f1]<d[f2]){ swap(f1,f2);swap(u,v); } Insert(1,1,pos,p[f1],p[u],w); u=Fa[f1];f1=Top[u]; } if (u==v)return ; if (d[u]<d[v])swap(u,v); Insert(1,1,pos,p[Son[v]],p[u],w);}int main(){ //freopen("1.txt","r",stdin); while (scanf("%d%d",&n,&m)!=EOF){ for (int i=1;i<=n;i++)V[i].clear(); for (int i=1;i<n;i++){ int u,v,w;scanf("%d%d%d",&u,&v,&w); Edge[i][0]=u; Edge[i][1]=v; Edge[i][2]=w; V[u].push_back(v); W[u].push_back(w); V[v].push_back(u); W[v].push_back(w); } for (int i=1;i<=n;i++)Son[i]=-1; pos=0; dfs1(1,0,0); dfs2(1,1); //for (int i=1;i<=n;i++)printf("%d:%d\n",i,p[i]); for (int i=1;i<n;i++){ if (d[Edge[i][0]]<d[Edge[i][1]]) swap(Edge[i][0],Edge[i][1]); vp[p[Edge[i][0]]]=Edge[i][2]; //Insert(1,1,pos,p[Edge[i][0]],p[Edge[i][0]],Edge[i][2]); } Build(1,1,pos); /*for (int i=1;i<(n<<2);i++){ printf("%d:%d %d %d\n",i,T[i].cl,T[i].cr,T[i].m); }*/ char str[10]; while (m--){ scanf("%s",str); if (str[0]=='Q'){ int x,y;scanf("%d%d",&x,&y); printf("%d\n",Query(x,y)); }else{ int x,y,z;scanf("%d%d%d",&x,&y,&z); Change(x,y,z); } } } return 0;}
0 0
- 2016ACM/ICPC Shengyang Online-1002 List wants to travel
- 2016 ACM/ICPC Reginal Shengyang hdu 5893 List wants to travel(树链剖分 线段树区间更新真蛋疼)★
- 2016 ACM/ICPC Asia Regional Shenyang Online HDU 5893 List wants to travel
- HDU5893 List wants to travel (树链剖分 + 线段树) 2016 ACM/ICPC Asia Regional Shenyang Online
- hdu 5893 List wants to travel 2016ACM/ICPC沈阳赛区网络赛1002
- 模板【HDU5893 2016 ACM ICPC Asia Regional Shenyang Online B】【树链剖分 权在边上 链值合并 结构体写法】List wants to travel
- hdu 5892 List wants to travel 2016ACM/ICPC沈阳赛区网络赛1001
- List wants to travel
- 2016ACM/ICPC Shengyang Online-1001 Resident Evil
- hdu5893 List wants to travel
- Hdu-5893 List wants to travel(树链剖分)
- [树链剖分] HDU 5893 List wants to travel
- HDU 5893 List wants to travel
- HDU 5893 List wants to travel 树链剖分
- hdu 5893 List wants to travel
- HDU 5893 List wants to travel
- [hdu5898]ACM/ICPC Reginal Shengyang
- hdu5893List wants to travel
- http的一个在线工具(推荐)
- Qt之QStringListModel
- RDLC 使用经验谈
- Android框架学习笔记03Retrofit框架
- Mac下ZooKeeper环境部署,Linux方法相同
- 2016ACM/ICPC Shengyang Online-1002 List wants to travel
- Cygwin安装和配置
- 超高清视频体验-4K片源
- Xcode8 创建NSManageObject subclass方法
- QT之QTableWidget
- freemarker单问号,双问号,感叹号的用法
- Android动画(链接好文)
- Android常用控件之悬浮窗(Service实现)
- jni使用c语言调用android shell命令方法