【GDSOI2017】中学生数据结构题
来源:互联网 发布:sql课程设计说明书模板 编辑:程序博客网 时间:2024/04/24 20:04
Description
Input
第一行有一个整数 N,表示 S 国城市的数量。
接下来有 N-1 行,每行两个数 u,v 表示一条道路。
第 N+1 行为一个整数 Q,表示接下来有 Q 个操作。
接下来有 Q 行,每行表示一个操作,格式如题目描述所示。
Output
对于每一个 QUERY 操作,输出一个数,表示询问的当前编号为 X 和编号为 Y 的城市的最短路径间的城市 (包括编号为 X 的城市和编号为 Y 的城市)的士兵总和。
Sample Input
Sample Input1:
5
1 2
1 3
3 4
3 5
6
ADD 1 5 2
ADD 3 4 1
QUERY 1 4
SHIFT 1 4
ADD 5 4 1
QUERY 4 5
Sample Input12:
5
1 2
2 3
3 4
4 5
5
ADD 1 3 2
ADD 3 5 1
SHIFT 2 4
QUERY 1 3
QUERY 1 5
Solution
GDOI必有一题数据结构防AK题
此题有两种解法
第一种
(我不是用的这种)
这种方法思考和实现起来比较简单,细节也比较少,但是码量比第二种大,大概5000~6000Byte
用树链剖分和splay来维护,对于每一个重链和每一个轻边建一颗splay
add和query很简单,用常规的树链剖分做法做就行了
shift操作在两颗splay中间时要注意,把前面的最后一个点接到后面的第一个点之前,再把最前面和最后面的splay维护一下即可
第二种
(我用的是这种方法)
用LCT维护
shift操作时要断点和连点,所以splay会被破坏,所以要两棵LCT
一棵是编号LCT,一棵是权值LCT
在makeroot,access等时,编号LCT的编号是固定的,可直接使用
在access的时候,splay的形态会改变,同时要保证两棵LCT形态完全相同
在add,shift,query时,找到编号LCT中某个点对应在权值LCT中的点,然后求值
那么怎样找编号LCT中某个点对应的权值LCT中的点呢?
需要记录下编号LCT中的每棵splay的根对应的权值LCT中的每棵splay的根是哪一个,反过来也需要记录下来,这个只用在access和rotate的时候维护
因为两棵LCT形态相同,所以中序遍历的点是相同的
所有找对应点时,利用编号LCT中点的位置,通过中序遍历找到权值LCT对应的点
然后就愉快的码吧
Code
#include<cstdio>#include<cstring>#include<algorithm>#define N 101000#define fo(i,a,b) for(int i=a;i<=b;i++)#define ll long longusing namespace std;int p[N],fa[2][N],t[2][N][2],rev[2][N],n,root[2][N],s[N];ll lz[N],sum[N],d[N],size[2][N];int lr(int qq,int x){return x==t[qq][fa[qq][x]][1];}void down(int qq,int x){ if(rev[qq][x]) { swap(t[qq][x][0],t[qq][x][1]); rev[qq][t[qq][x][0]]^=1;rev[qq][t[qq][x][1]]^=1; rev[qq][x]=0; } if(qq==1) { if(lz[x]) { if(t[1][x][0]) d[t[1][x][0]]+=lz[x],sum[t[1][x][0]]+=lz[x]*size[1][t[1][x][0]],lz[t[1][x][0]]+=lz[x]; if(t[1][x][1]) d[t[1][x][1]]+=lz[x],sum[t[1][x][1]]+=lz[x]*size[1][t[1][x][1]],lz[t[1][x][1]]+=lz[x]; lz[x]=0; } }}int kth(int r,int x){ down(1,r); if(x==size[1][t[1][r][0]]+1) return r; if(x<=size[1][t[1][r][0]]) return kth(t[1][r][0],x); else return kth(t[1][r][1],x-size[1][t[1][r][0]]-1);}void update(int qq,int x){ size[qq][x]=size[qq][t[qq][x][0]]+size[qq][t[qq][x][1]]+1; if(qq==1) sum[x]=sum[t[1][x][0]]+sum[t[1][x][1]]+d[x];}void rotate(int qq,int x){ int y=fa[qq][x],k=lr(qq,x); t[qq][y][k]=t[qq][x][1-k];if(t[qq][x][1-k]) fa[qq][t[qq][x][1-k]]=y; fa[qq][x]=fa[qq][y]; if(fa[qq][y]) t[qq][fa[qq][y]][lr(qq,y)]=x; else { root[qq][x]=root[qq][y];root[1-qq][root[qq][y]]=x; if(qq==0) p[x]=p[y],p[y]=0; } fa[qq][y]=x;t[qq][x][1-k]=y; update(qq,y);update(qq,x);}void xc(int qq,int x){ for(;x;x=fa[qq][x]) s[++s[0]]=x; for(;s[0];s[0]--) down(qq,s[s[0]]);}void splay(int qq,int x,int y){ xc(qq,x); while(fa[qq][x]!=y) { if(fa[qq][fa[qq][x]]!=y) if(lr(qq,x)==lr(qq,fa[qq][x])) rotate(qq,fa[qq][x]); else rotate(qq,x); rotate(qq,x); }}int get(int x){ splay(1,root[0][x],0); return kth(root[0][x],size[0][t[0][x][0]]+1);}void access(int x){ int y=0,yy=0; while(x>0) { splay(0,x,0); int xx=get(x); splay(1,xx,0); fa[0][t[0][x][1]]=0;p[t[0][x][1]]=x; fa[1][t[1][xx][1]]=0; root[0][t[0][x][1]]=t[1][xx][1]; root[1][t[1][xx][1]]=t[0][x][1]; t[0][x][1]=y; t[1][xx][1]=yy; fa[0][y]=x;p[y]=0; fa[1][yy]=xx; update(0,x);update(1,xx); y=x;x=p[x];yy=xx; }}void makeroot(int x){ access(x); splay(0,x,0); rev[0][x]^=1; int xx=get(x); splay(1,xx,0); rev[1][xx]^=1;}void link(int x,int y){ makeroot(x);p[x]=y;}int main(){ freopen("shift.in","r",stdin); freopen("shift.out","w",stdout); scanf("%d",&n); fo(i,1,n) root[0][i]=root[1][i]=i; fo(i,1,n-1) { int x,y;scanf("%d%d",&x,&y); link(x,y); } int ac;scanf("%d\n",&ac); for(;ac;ac--) { char ch;scanf("%c",&ch); int x,y;ll z; if(ch=='A') { scanf("DD%d%d%d\n",&x,&y,&z); makeroot(x); access(y); splay(0,x,0); int x1=get(x); splay(1,x1,0); d[x1]+=z;sum[x1]+=z*size[1][x1];lz[x1]+=z; } if(ch=='S') { scanf("HIFT%d%d\n",&x,&y); if(x==y) continue; makeroot(x);access(y); splay(0,x,0); int xx=get(x); splay(0,y,0); int yy=get(y); splay(1,yy,0);fa[1][t[1][yy][0]]=0,t[1][yy][0]=0; splay(1,xx,0);fa[1][t[1][yy][1]=xx]=yy,root[0][y]=yy; } if(ch=='Q') { scanf("UERY%d%d\n",&x,&y); makeroot(x);access(y); splay(0,x,0); int x1=get(x); splay(1,x1,0); printf("%lld\n",sum[x1]); } }}
- 【GDSOI2017】 中学生数据结构题
- 【GDSOI2017】中学生数据结构题
- 【GDSOI2017】 中学生数据结构题(LCT)
- GDSOI2017 中学生数据结构题(Lct练习)
- 中学生数据结构题
- 【GDSOI 2017】【JZOJ 5107】中学生数据结构题
- 【GDOI 2016 Day1】第一题 中学生数学题
- GDSOI2017模拟
- 【GDSOI2017】 逃亡
- GDOI 2016 Day1 第一题 中学生数学题 解题报告
- JZOJ 4485【GDOI 2016 Day1】第一题 中学生数学题
- 中学生学习方法
- 中学生学习方法
- 中学生学习方法
- 中学生学习方法
- 【GDSOI2017模拟】奶酪
- 【GDSOI2017模拟】树
- 【GDSOI2017模拟】Travel Plan
- 修改input元素的file样式
- 查找——线性表的查找
- 【剑指offer】面试题 8:二叉树的下一个节点
- 深入了解Windows句柄到底是什么(转)
- poj 2187 Beauty Contest(凸包)
- 【GDSOI2017】中学生数据结构题
- 学习资料
- inet_pton函数 和inet_ntop函数
- 部署描述文件web.xml解析(六) 配置应用程序监听器
- Java中的ThreadLocal
- Python中为什么没有switch-case
- Spring框架的特性
- ubuntu系统备份与恢复-remastersys方法
- Leetcode 460. LFU Cache