好久没写数据结构了

来补一发

果然写的时候思路极其混乱....

LOJ #2116 Luogu P3241


题意

$ Q$次询问,求树上点的颜色在$ [L,R]$中的所有点到询问点的距离 强制在线

询问次数,树上点数约$ 2·10^5$


$ Solution$

首先有

$ dist(x,y)=deep(x)+deep(y)-2·deep(lca(x,y))$

显然这个等式的前两项很容易用前缀和什么的维护

只考虑第三项的话相当于是有边权并且强制在线的「LNOI2014」LCA

用同样的套路将$ deep(lca(x,y))$转化成对于所有在区间中的点,将其到根的路径区间加

然后查询询问点到根的距离

将所有点按颜色排序 树剖+主席树维护

每次将当前颜色最小的点插入主席树 最多影响$ log^2$个线段

注意需要标记永久化

写的时候思路很不清楚感觉写了假的主席树


$my \ code$

#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define M 150010
#define rt register int
#define ll long long
using namespace std;
inline ll read(){
ll x=;char zf=;char ch=getchar();
while(ch!='-'&&!isdigit(ch))ch=getchar();
if(ch=='-')zf=-,ch=getchar();
while(isdigit(ch))x=x*+ch-'',ch=getchar();return x*zf;
}
void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
void writeln(const ll y){write(y);putchar('\n');}
int k,m,n,x,y,z,cnt,ans;
int dfn[M],top[M],size[M],fa[M],to[M];ll deep[M];
vector<pair<int,int>>e[];
void dfs(int x,int pre){
size[x]=;fa[x]=pre;
for(auto i:e[x])if(i.first!=pre){
deep[i.first]=deep[x]+i.second;
dfs(i.first,x);size[x]+=size[i.first];
}
}
void dfs2(int x,int chain){
int heavy=;dfn[x]=++cnt;top[x]=chain;to[cnt]=x;
for(auto i:e[x])if(size[i.first]>size[heavy]&&i.first!=fa[x])heavy=i.first;
if(!heavy)return;
dfs2(heavy,chain);
for(auto i:e[x])if(i.first!=heavy&&i.first!=fa[x])dfs2(i.first,i.first);
}
struct segment{
int ls,rs,tag;ll sum;
}a[];
int Root[];
#define up a[x].sum=(ll)a[a[x].ls].sum+a[a[x].rs].sum+(ll)a[x].tag*(deep[to[R]]-deep[fa[to[L]]])
void change(int x,int L,int R,int LL,int RR){
const int mid=L+R>>;
if(L>=LL&&R<=RR){
a[x].tag++;
up;return;
}
if(mid>=LL){
if(a[x].ls)a[cnt+]=a[a[x].ls];
change(a[x].ls=++cnt,L,mid,LL,RR);
}
if(mid+<=RR){
if(a[x].rs)a[cnt+]=a[a[x].rs];
change(a[x].rs=++cnt,mid+,R,LL,RR);
}
up;
}
ll query(int x,int LL,int RR,int L,int R,int cs){
if(!x)x=++cnt;if(LL>R||RR<L)return ;
if(LL>=L&&RR<=R)return a[x].sum+(ll)cs*(deep[to[RR]]-deep[fa[to[LL]]]);
const int mid=LL+RR>>;
return query(a[x].ls,LL,mid,L,R,cs+a[x].tag)+query(a[x].rs,mid+,RR,L,R,cs+a[x].tag);
}
void upd(int id,int x){
while(x){
change(Root[id],,n,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
}
ll query(int id,int x){
if(!id)return ;
ll ans=;
while(x){
ans+=query(Root[id],,n,dfn[top[x]],dfn[x],);
x=fa[top[x]];
}
return ans;
}
struct peri{
int x,id;
bool operator <(const peri s){
return x<s.x;
}
}q[];
ll s[];
int main(){
n=read();m=read();int A=read();
for(rt i=;i<=n;i++)q[i].x=read(),q[i].id=i;
sort(q+,q+n+);fa[]=;
for(rt i=;i<=n;i++){
x=read();y=read();z=read();
e[x].push_back({y,z});e[y].push_back({x,z});
}
dfs(,);dfs2(,);cnt=;
for(rt i=;i<=n;i++)s[i]=s[i-]+deep[q[i].id];//前i小的deep和
for(rt i=;i<=n;i++){
Root[i]=++cnt;
a[Root[i]]=a[Root[i-]];
upd(i,q[i].id);
}
ll las=;
while(m--){
z=read();int aa=read(),bb=read();
int L=min((aa+las)%A,(bb+las)%A);
int R=max((aa+las)%A,(bb+las)%A);
L=lower_bound(q+,q+n+,(peri){L,})-q;
R=lower_bound(q+,q+n+,(peri){R+,})-q-;
las=(ll)(R-L+)*deep[z]+s[R]-s[L-]-(query(R,z)-query(L-,z))*;
writeln(las);
}
return ;
}

LOJ #2116 Luogu P3241「HNOI2015」开店的更多相关文章

  1. loj #2116. 「HNOI2015」开店

    #2116. 「HNOI2015」开店 题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的想法当然非 ...

  2. LOJ #2547 Luogu P4517「JSOI2018」防御网络

    好像也没那么难写 LOJ #2547 Luogu P4517 题意 在一棵点仙人掌中等概率选择一个点集 求选出点集的斯坦纳树大小的期望 定义点仙人掌为不存在一个点在多个简单环中的连通图 斯坦纳树为在原 ...

  3. LOJ#2249 Luogu P2305「NOI2014」购票

    几乎肝了半个下午和整个晚上 斜率优化的模型好多啊... LOJ #2249 Luogu P2305 题意 给定一棵树,第$ i$个点如果离某个祖先$ x$的距离不超过$ L_i$,可以花费$ P_i· ...

  4. LOJ #2527 Luogu P4491「HAOI2018」染色

    好像网上没人....和我推出....同一个式子啊..... LOJ #2527 Luogu P4491 题意 $ n$个格子中每个格子可以涂$ m$种颜色中的一种 若有$ k$种颜色恰好涂了$ s$格 ...

  5. 【LOJ】#2116. 「HNOI2015」开店

    题解 一道我觉得和二叉树没有关系的题-- 因为直接上点分就过了,虽然很慢,而且代码很长 你需要记录一个点分树,对于每个点分树的重心,记录一下上一次进行分割时树的重心以及这个重心和上一次重心所连接的点以 ...

  6. [loj2116]「HNOI2015」开店 动态点分治

    4012: [HNOI2015]开店 Time Limit: 70 Sec  Memory Limit: 512 MBSubmit: 2452  Solved: 1089[Submit][Status ...

  7. 「HNOI2015」开店(树链剖分, 主席树)

    /* 考虑将所求的值拆分 记每个点到根的路径长度为dis_i, 那么我们要求的就是\sum_{i = l} ^ r dis_i + dis[u] * (r - l + 1) - 2\sum_{i = ...

  8. 「HNOI2015」菜肴制作

    「HNOI2015」菜肴制作 这道题想到了其实还挺水的,一开始我直接用小根堆拓扑然后就爆0了,然后我又用十万个堆搜索,T30,还是xkl告诉我要倒着拓扑. 首先要建反图,对于入度为0的点,较小的点先输 ...

  9. 【LOJ】#2117. 「HNOI2015」实验比较

    题解 把所有=的点连起来,一个图合法肯定它是一个有向树森林 我们新建一个点,把这个点和其他所有树的树根连起来 定义\(dp[u][j]\)表示第u个点长度为j的序列的方案数 转移方法是 \(dp[u] ...

随机推荐

  1. Vue项目中的RSA加解密

    前后端使用rsa加密:  一般是客户端初始化时访问登录服务时,服务端面动态生成一对RSA对,公钥传给客户端,客户端拿到后,用户输入密码后,点登录时用公钥加密返回给服务端,服务端用私钥解就行了 一.安装 ...

  2. Git拉取、提交、迁出、合并、删除分之命令

    #拉取代码 git clone -b 分之名称 git地址 #提交代码 git add . //:注释,if是第一次提交: $ git add --all . (请注意后面有个英文点(表示是当前目录) ...

  3. 【Windows】+ win10 通过KMS激活

    win10激活到期 通过KMS再次激活(亲测有效):http://www.xitongcheng.com/jiaocheng/win10_article_44435.html

  4. java将对象转map,map转对象工具类

    /** * 将map转换为一个对象 * * @param map * @param beanClass * @return * @throws Exception */ public static O ...

  5. python中的数组和列表

    ####转自:模式识别实验室主任   #环境win64+anaconda+python3.6 list & array (1)list不具有array的全部属性(如维度.转置等) 代码1: # ...

  6. python和anacoda安装第三方库的位置

    查看已安装库及版本号,命令行pip list 安装第三方库位置:

  7. Django模板语言进阶

    一.母板 1.什么情况下使用母版 当多个页面的大部分内容都一样的时候,我们可以把相同的部分提取出来,放到一个单独的母版HTML文件中 然后在母版中定义需要被替换的block 例如:母板页面 <! ...

  8. JS异常

    当 JavaScript 引擎执行 JavaScript 代码时,会发生各种错误. 可能是语法错误,通常是程序员造成的编码错误或错别字. 可能是拼写错误或语言中缺少的功能(可能由于浏览器差异). 可能 ...

  9. centos7虚拟机下python3安装matplotlib遇到的一些问题

    1.安装位置 centos7虚拟机+python3.6 2.问题 2.1如果是使用的python2版本可以使用如下方式, #yum search matplotlib 返回如下: 已加载插件:fast ...

  10. nuxt.js实战之引入jquery

    head: { title: 'nuxt', meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-widt ...