博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[CodeChef-QUERY]Observing the Tree
阅读量:5888 次
发布时间:2019-06-19

本文共 2487 字,大约阅读时间需要 8 分钟。

题目大意:

  给你一棵树,一开始每个点的权值都是0,要求支持一下三种操作:
    1.路径加等差数列。
    2.路径求和。
    3.回到以前的某次操作。
  强制在线。

思路:

  树链剖分+主席树。
  最坏情况下,n个点的树最多会被分成n-1个链,
  这里不能每个点都开一个主席树,因为主席树中要存每个线段树的根结点编号,总共有m次操作,
  因此最坏情况下,总共要存nm个根结点,显然会爆空间,因此我们可以考虑将所有点合并在一个主席树中。
  路径加等差数列时,我们可以先求出两个端点x和y上加的值ax和ay,然后往上爬的过程中根据跳过的长度维护ax和ay即可。
  交换x和y的时候就相当于翻转等差数列,只要交换ax和ay并对公差b取反即可。
  然后随随便便就跑了Rank2(Rank2的vjudge7和Rank3的skylee都是我的程序),0.63s。
  后来想抢Rank发现刷不上去了(似乎CodeChef是根据第一次交的程序来排名的)。
  交的时候发现忘记处理强制在线的操作也能AC?

细节:

  题目中回退操作以后并不能删掉中间被跳过的操作,比如从第四次操作回退到第三次操作,如果再进行一次修改,那么这个修改操作就是第五次操作。

 

1 #include
2 #include
3 #include
4 #include
5 inline int getint() { 6 char ch; 7 while(!isdigit(ch=getchar())); 8 int x=ch^'0'; 9 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 10 return x; 11 } 12 const int V=100001,logV=200,M=100001; 13 std::vector
e[V]; 14 inline void add_edge(const int u,const int v) { 15 e[u].push_back(v); 16 } 17 int par[V],size[V],son[V],top[V],dep[V],id[V],cnt; 18 void dfs1(const int x,const int p) { 19 dep[x]=dep[p]+1; 20 par[x]=p; 21 size[x]=1; 22 for(unsigned i=0;i
size[son[x]]) son[x]=y; 28 } 29 } 30 void dfs2(const int x) { 31 top[x]=x==son[par[x]]?top[par[x]]:x; 32 id[x]=++cnt; 33 if(son[x]) dfs2(son[x]); 34 for(unsigned i=0;i
>1; 66 if(l<=mid) modify(left[p],left[old_p],b,mid,l,std::min(mid,r),x,y); 67 if(r>mid) modify(right[p],right[old_p],mid+1,e,std::max(mid+1,l),r,x+(std::max(mid+1,l)-l)*y,y); 68 if(!left[p]) left[p]=left[old_p]; 69 if(!right[p]) right[p]=right[old_p]; 70 push_up(p,b,e); 71 } 72 long long query(const int p,const int b,const int e,const int l,const int r) { 73 if(!p) return 0; 74 if((b==l)&&(e==r)) return sum[p]; 75 int mid=(b+e)>>1; 76 long long ret=(first[p]*2+(l+r-b*2)*diff[p])*(r-l+1)/2; 77 if(l<=mid) ret+=query(left[p],b,mid,l,std::min(mid,r)); 78 if(r>mid) ret+=query(right[p],mid+1,e,std::max(mid+1,l),r); 79 return ret; 80 } 81 }; 82 FotileTree t; 83 inline int get_lca(int x,int y) { 84 while(top[x]!=top[y]) { 85 if(dep[top[x]]
dep[y]) std::swap(x,y); 89 return x; 90 } 91 int n; 92 inline void modify(const int old_root,int &root,int x,int y,const long long a,long long b) { 93 int lca=get_lca(x,y); 94 int dis=dep[x]+dep[y]-dep[lca]*2; 95 int ax=a,ay=a+b*dis; 96 while(top[x]!=top[y]) { 97 if(dep[top[x]]

 

转载于:https://www.cnblogs.com/skylee03/p/7491642.html

你可能感兴趣的文章
安装cobbler
查看>>
第3章 方法的重载及参数传递
查看>>
多选下拉相互切换
查看>>
SSH服务详解
查看>>
小程序--时间处理(显示几分钟前,,几小时前,,几天前...)
查看>>
23种设计模式介绍(三)---- 行为型模式
查看>>
项目owner看这里,MaxCompute全表扫描新功能,给你“失误”的机会
查看>>
2018-07-16笔记(tomcat 配置)
查看>>
用框架思维解读生活目标
查看>>
selinux
查看>>
ci完整集成
查看>>
深度学习目标检测(object detection)系列(二) SPP-Net
查看>>
Python类、模块、包的概念及区别
查看>>
FreeMarker笔记 第四章 其它
查看>>
Oracle 11g 新特性简介(一)
查看>>
详解Oracle的几种分页查询语句
查看>>
从零部署RHEV3.3红帽虚拟化-2 (用kvm虚拟机安装RHEL6.4)
查看>>
Varnish 3.X详解
查看>>
javascript继承方式详解
查看>>
lnmp环境安装sh脚本
查看>>