Link

纪念一下场切题。

题意:给定一棵(分点不一定为中点)的线段树,给定若干个询问区间,问有多少个线段树上结点的集合,知道了这些结点对应的区间和就可以知道任何一个询问区间的和。


从询问区间开始考虑。会发现可以把所有 \(a_i\) 分成若干个集合,只要知道每个集合的和就可以知道所有询问区间的和。具体地,“被覆盖情况”相同的 \(a_i\) 是在同一个集合中的。特别的,可能有一些 \(a_i\) 没有被任何询问区间覆盖,这些 \(a_i\) 分到一个集合,它们的和可以不用求出。这个集合具体的分法可以用一个哈希处理,给每个区间赋一个权值,区间中每个点加上这个权值,就可以认为权值相同的点属于一个集合。

再考虑到线段树上的区间。可以认为我们标记了一些节点,知道了它们对应区间的和。同样的,通过上面的分类方法可以把所有 \(a_i\) 拆成若干个集合,知道了每个集合的和(以及有一个集合不知道)。进一步地,利用这个树形结构,会发现“祖先中自下而上第一个标记结点”相同的 \(a_i\) 是分在同一个集合里的。

考虑两组分类的关系。我们需要满足询问,所以第一种分类方式中不同集合的两个 \(a_i\) 在第二种分类方式中不能分在同一集合。也就是说第一组集合进一步拆分得到了第二组集合。容易发现这个条件是充要的。

下面来考虑一下特殊性质。特殊性质相当于第一种分类方式有 \(n\) 个集合 \(\{1\},\{2\},\cdots,\{n\}\),它们的和都需要知道。从刚才说明的第二种分类的判断方法入手,考虑做一个树形 DP,自下而上确定。根据刚才的充要条件,对某个点 \(u\),确定了它的子树的选择情况后,子树内的所有 \(a_i\) 至多有一个的分类(即第一个祖先)还没有确定。 那么就可以设 \(f_u\) 表示子树 \(u\) 内所有 \(a_i\) 的分类都确定的方案数,\(g_u\) 表示子树 \(u\) 内有一个 \(a_i\) 的分类还没有确定的方案数。设 \(u\) 的左右儿子分别为 \(ls,rs\),有

\[f_{u}=2f_{ls}f_{rs}+f_{ls}g_{rs}+g_{ls}f_{rs}
\]
\[g_{u}=f_{ls}g_{rs}+g_{ls}f_{rs}
\]

初始值是对于叶子结点 \(v\),\(f_v=g_v=1\)。答案是 \(f_{1}\)。这样就可以通过特殊性质。

再来处理一般情况。容易把刚才的性质推广:一棵子树完全确定后,至多有一类结点的分类(第一个祖先)还没有确定。那么就可以设计一个二维DP:\(dp_{u,i}\) 表示子树 \(u\) 内的方案确定后,第 \(i\) 个集合的点的分类还没有确定。特别地,\(i=0\) 表示都已经确定,\(i=1\) 表示这一类的和可以不用求,也就是它们可以没有“第一个标记的祖先”。转移为

\[dp_{u,i}=dp_{ls,0}dp_{rs,i}+dp_{ls,i}dp_{rs,0}+dp_{ls,i}dp_{rs,i}
\]
\[dp_{u,0}=2dp_{ls,0}dp_{rs,0}+\sum dp_{u,i}
\]

初始值是对于叶子结点 \(v\),如果它在第 \(i\) 类,有 \(dp_{v,0}=dp_{v,i}=1\)。答案是 \(dp_{1,0}+dp_{1,1}\)。直接做这个 DP,复杂度是 \(O(n\times\min(n,m))\),结合特殊性质可以获得 \(85\) 分。

最后 \(15\) 分,只需要记录 \(dp_u\) 中每个非零数,做启发式合并即可。具体的,需要维护一个乘法标记,以及 \(\sum_{i\neq 0} dp_{u,i}\)。使用 map 实现,时间复杂度是 \(O(n\log^2 n)\)。

中间有一步除法,可能遇到除以 \(0\) 的情况,所以需要特殊处理(是容易的)。场上当然没有考虑到,不过良心出题人 jiangly 在 WC 的数据里并没有卡,赞美良心出题人!

代码是赛后补的。

upd on 2024.3.19:更新了代码,现在能够通过 CTS 的数据了。

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
mt19937_64 rnd(time(0));
const int N=4e5+5,P=998244353;
int qpow(int a,int b=P-2){
int c=1;
for(;b;b>>=1,a=1ll*a*a%P)
if(b&1)c=1ll*c*a%P;
return c;
}
int n,m,tot=1,typ[N];ull h[2][N];
struct node{int ls,rs,l,r;}tr[N];
void build(int p,int l,int r){
tr[p].l=l;tr[p].r=r;
if(l==r)return;
int mid;scanf("%d",&mid);
tr[p].ls=++tot;build(tot,l,mid);
tr[p].rs=++tot;build(tot,mid+1,r);
}
vector<pair<ull,ull> > vec;
map<int,int> dp[N];int to[N],mul[N],sum[N];
int main(){
scanf("%d%d",&n,&m);build(1,1,n);
for(int i=1,l,r;i<=m;i++){
scanf("%d%d",&l,&r);++l;++r;
ull v0=rnd(),v1=rnd();
h[0][l]+=v0;h[0][r]-=v0;
h[1][l]+=v1;h[1][r]-=v1;
}
for(int i=1;i<=n;i++){
h[0][i]+=h[0][i-1];h[1][i]+=h[1][i-1];
vec.push_back({h[0][i],h[1][i]});
}
vec.push_back({0,0});sort(vec.begin(),vec.end());
for(int i=1;i<=n;i++)typ[i]=lower_bound(vec.begin(),vec.end(),
make_pair(h[0][i],h[1][i]))-vec.begin()+1;
for(int i=2*n-1;i>=1;i--){
if(!tr[i].ls){
dp[i][0]=dp[i][typ[tr[i].l]]=1;
to[i]=i;mul[i]=sum[i]=1;continue;
}
int x=to[tr[i].ls],y=to[tr[i].rs];
if(dp[x].size()<dp[y].size())swap(x,y);
int vl=dp[x][0],vr=dp[y][0];
if(vr==0){
to[i]=i;mul[i]=1ll*mul[x]*mul[y]%P;
for(auto it:dp[y]){
int c=it.first,f=it.second;
if(c==0)continue;
dp[i][c]=1ll*(vl+dp[x][c])*f%P;
sum[i]=(sum[i]+dp[i][c])%P;
}
dp[i][0]=sum[i];
}
else{
mul[x]=1ll*mul[x]*mul[y]%P*vr%P;
dp[x][0]=(vl+vl)%P;to[i]=x;vr=qpow(vr);
for(auto it:dp[y]){
int c=it.first,f=it.second;
if(c==0)continue;
int tmp=1ll*f*(dp[x][c]+vl)%P*vr%P;
dp[x][c]=(dp[x][c]+tmp)%P;
sum[x]=(sum[x]+tmp)%P;
}
dp[x][0]=(dp[x][0]+sum[x])%P;
}
}
int ans=(dp[to[1]][0]+dp[to[1]][1])%P;
ans=1ll*ans*mul[to[1]]%P;
printf("%d\n",ans);
return 0;
}

[WC/CTS2024] 线段树 题解的更多相关文章

  1. 「洛谷 P3834」「模板」可持久化线段树 题解报告

    题目描述 给定n个整数构成的序列,将对于指定的闭区间查询其区间内的第k小值. 输入输出格式 输入格式 第一行包含两个正整数n,m,分别表示序列的长度和查询的个数. 第二行包含n个整数,表示这个序列各项 ...

  2. HDU 1556 Color the Ball 线段树 题解

    本题使用线段树自然能够,由于区间的问题. 这里比較难想的就是: 1 最后更新须要查询全部叶子节点的值,故此须要使用O(nlgn)时间效率更新全部点. 2 截取区间不能有半点差错.否则答案错误. 这两点 ...

  3. POJ1389:Area of Simple Polygons——扫描线线段树题解+全套代码注释

    http://poj.org/problem?id=1389 题面描述在二维xy平面中有N,1 <= N <= 1,000个矩形.矩形的四边是水平或垂直线段.矩形由左下角和右上角的点定义. ...

  4. POJ 2528 Mayor&#39;s posters 离散化和线段树题解

    本题就是要往墙上贴海报,问最后有多少可见的海报. 事实上本题的难点并非线段树,而是离散化. 由于数据非常大,直接按原始数据计算那么就会爆内存和时间的. 故此须要把数据离散化. 比方有海报1 6   7 ...

  5. poj 3468 A Simple Problem with Integers 线段树 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=3468 线段树模板 要背下此模板 线段树 #include <iostream> #include <vector> ...

  6. 洛谷 P3919 可持久化线段树 题解

    题面 这题好水的说~很明显就是主席树的大板子 然而我交了3遍才调完所有的BUG,开好足够的数组,卡掉大大的常数: 针对与每次操作,change()会创建新节点,而ask()虽然也会更新左右儿子的节点编 ...

  7. 【CJOJ2316】【模板】可持久化线段树

    题面 Description 这是一道非常直白的可持久化线段树的练习题,目的并不是虐人,而是指导你入门可持久化数据结构. 线段树有个非常经典的应用是处理RMQ问题,即区间最大/最小值询问问题.现在我们 ...

  8. cogs 2554. [福利]可持久化线段树

    题目链接 cogs 2554. [福利]可持久化线段树 题解 没有 代码 #include<cstdio> #include<cstring> #include<algo ...

  9. B. Interesting Array(线段树)

    B. Interesting Array time limit per test 1 second memory limit per test 256 megabytes input standard ...

  10. HDU 5249:KPI(权值线段树)

    KPI Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Desc ...

随机推荐

  1. 一键生成项目 SpringBoot+MyBatis代码生成器 支持Oracle MySQL PostgreSQL

    下载地址 https://github.com/lxw112190/lxw_Helper 如果觉得github下载慢的,可以加我QQ(819069052)我发给你,或者加QQ交流群:758616458 ...

  2. 可变形卷积系列(二) MSRA提出升级版DCNv2,变形能力更强 | CVPR 2019

    论文提出DCNv2,不仅对DCNv1的结构进行了改进,还使用了有效的蒸馏学习策略,使得性能有很大的提升,各个方面都值得借鉴   来源:晓飞的算法工程笔记 公众号 论文: Deformable Conv ...

  3. 论文阅读小结(B/S和C/S结构)

    论文阅读小结 一.B/S 和 C/S 软件体系结构选择 1) C/S . B/S 结构概述 C/S 结构,即 Client/Server (客户机 / 服务器 ), C/S 结构软件分为客户机和服务器 ...

  4. 【已解决】Android----java.lang.NullPointerException:---java.lang.NullPointerException:

    2021-03-06 13:26:12.274 8544-8544/com.example.helloworld E/AndroidRuntime: FATAL EXCEPTION: main Pro ...

  5. NodeJS 实战系列:模块设计与文件分类

    我们从一个最简单的需求开始,来探索我们应该从哪些方面思考模块设计,以及如何将不同的文件分类.之所以说"思考",是因为我在这篇文章里更多的是提供一类解决问题的范式,而非统一的标准答案 ...

  6. vue前后端分离项目,使用宝塔面板解决跨域问题,设置Nginx反向代理

    开发环境解决跨域问题: 使用教程 跨域解决本地跨域问题 非唯一方法 生成环境解决跨域问题: 1.创建站点 2.把打包的vue项目dist发送解压到站点里面 ,选择静态模式 3.然后设置反向代理 目标u ...

  7. npm 直接安装 GitHub/GitLab 仓库代码及 npm link 本地调试

    一.npm 直接安装 GitHub/GitLab 仓库代码 语法 npm install <git remote url> 示例 命令: npm i git@github.com:maze ...

  8. Tomcat内存马回显

    回顾JSP马 详情见:https://www.cnblogs.com/F12-blog/p/18111253 之前说的都是利用 jsp 注入内存马,但 Web 服务器中的 jsp 编译器还是会编译生成 ...

  9. 报名启动|OpenHarmony源码转换器—多线程特性转换赛题

  10. 如何在报表中绘制 SVG 统计图

    SVG 作为一种矢量图形,具有任意缩放不失真.可被高质量打印.文件较小.交互性强等优势,正逐渐成为一种主流的图片格式.润乾报表一方面可以生成 SVG 格式的统计图,另一方面也可以在 HTML5 中直接 ...