洛谷P5280 [ZJOI2019]线段树 [线段树,DP]
无限Orz \(\color{black}S\color{red}{ooke}\)……
思路
显然我们不能按照题意来每次复制一遍,而多半是在一棵线段树上瞎搞。
然后我们可以从\(modify\)函数入手,寻找一些性质。
(盗一张Sooke的图)

可以发现每次\(modify\)之中,所有节点都可以被分成5类:
- 白色:经过而且标记全都被下传的点。
- 黑色:打上标记的点。
- 灰色:在修改区域内但不会被经过的点。
- 橙色:可以享受到来自上方标记的滋润的点。
- 黄色:半毛钱关系都没有的点……
分类之后,可以发现:如果DP的话,所有同一类型的点的转移方程都是基本相同的。
于是考虑DP:很自然地,想到设\(f_i\)表示在所有情况中\(tag_i=1\)的情况个数。
那么有转移方程:
f_i&,white\\
f_i+2^t&,black\\
2f_i&,grey\\
2f_i&,yellow\\
?????&,orange
\end{cases}
\]
你发现橙色点还要根据上方点是否有标记来转移,烦死了。
于是再一次很自然地,想到设\(g_i\)表示在所有情况中\(i\rightarrow root\)路径上存在\(tag_x=1\)的情况个数。
那么有转移方程:
g_i&,white\\
g_i+2^t&,black\\
g_i+2^t&,grey\\
2g_i&,yellow\\
2g_i&,orange
\end{cases}
\]
然后终于可以得到:
\]
大功告成!
显然白色、黑色、橙色暴力转移,灰色、黄色随便维护下懒标记即可。
最后答案是\(\sum_i f_i\),也是在线段树上很好统计的。
代码
#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std{
using namespace std;
#define pii pair<int,int>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define templ template<typename T>
#define sz 202020
#define mod 998244353ll
typedef long long ll;
typedef double db;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
templ inline void read(T& t)
{
t=0;char f=0,ch=getchar();double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
t=(f?-t:t);
}
template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
char __sr[1<<21],__z[20];int __C=-1,__zz=0;
inline void Ot(){fwrite(__sr,1,__C+1,stdout),__C=-1;}
inline void print(register int x)
{
if(__C>1<<20)Ot();if(x<0)__sr[++__C]='-',x=-x;
while(__z[++__zz]=x%10+48,x/=10);
while(__sr[++__C]=__z[__zz],--__zz);__sr[++__C]='\n';
}
void file()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
}
inline void chktime()
{
#ifndef ONLINE_JUDGE
cout<<(clock()-t)/1000.0<<'\n';
#endif
}
#ifdef mod
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
ll inv(ll x){return ksm(x,mod-2);}
#else
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
#endif
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;
int n,m;
ll pow2;
ll f[sz<<2],g[sz<<2],fMul[sz<<2],gAdd[sz<<2],gMul[sz<<2];
ll S[sz<<2];
#define ls k<<1
#define rs k<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
void mulf(int k,ll w){(f[k]*=w)%=mod;(fMul[k]*=w)%=mod;(S[k]*=w)%=mod;}
void mulg(int k,ll w){(g[k]*=w)%=mod;(gMul[k]*=w)%=mod;(gAdd[k]*=w)%=mod;}
void addg(int k,ll w){(g[k]+=w)%=mod;(gAdd[k]+=w)%=mod;}
void pushdown(int k)
{
mulg(ls,gMul[k]);mulg(rs,gMul[k]);gMul[k]=1;
addg(ls,gAdd[k]);addg(rs,gAdd[k]);gAdd[k]=0;
mulf(ls,fMul[k]);mulf(rs,fMul[k]);fMul[k]=1;
}
void pushup(int k){S[k]=(S[ls]+S[rs]+f[k])%mod;}
void modify1(int k,int l,int r,int x,int y) // white,black,grey
{
pushdown(k);
int mid=(l+r)>>1;
if (x<=l&&r<=y) // black
{
(f[k]+=pow2)%=mod;
(g[k]+=pow2)%=mod;
addg(ls,pow2);addg(rs,pow2); // grey
mulf(ls,2);mulf(rs,2); // grey
pushup(k);
return;
}
// white (do nothing)
if (x<=mid) modify1(lson,x,y);
if (y>mid) modify1(rson,x,y);
pushup(k);
}
void modify2(int k,int l,int r,int x,int y) // orange,yellow
{
pushdown(k);
if (x<=l&&r<=y) // orange
{
(f[k]+=g[k])%=mod;(g[k]+=g[k])%=mod;
mulg(ls,2);mulg(rs,2); // yellow
mulf(ls,2);mulf(rs,2); // yellow
pushup(k);
return;
}
int mid=(l+r)>>1;
if (x<=mid) modify2(lson,x,y);
if (y>mid) modify2(rson,x,y);
pushup(k);
}
void build(int k,int l,int r)
{
f[k]=g[k]=0;
fMul[k]=gMul[k]=1;gAdd[k]=0;
if (l==r) return;
int mid=(l+r)>>1;
build(lson);build(rson);
}
int main()
{
file();
read(n,m);
build(1,1,n);
int z,x,y;
pow2=1;
while (m--)
{
read(z);
if (z==2) printf("%lld\n",S[1]);
else
{
read(x,y);
modify1(1,1,n,x,y);
if (x!=1) modify2(1,1,n,1,x-1);
if (y!=n) modify2(1,1,n,y+1,n);
(pow2*=2)%=mod;
}
}
return 0;
}
洛谷P5280 [ZJOI2019]线段树 [线段树,DP]的更多相关文章
- 洛谷P5280 [ZJOI2019]线段树
https://www.luogu.org/problemnew/show/P5280 省选的时候后一半时间开这题,想了接近两个小时的各种假做法,之后想的做法已经接近正解了,但是有一些细节问题理不 ...
- 洛谷 P5280 - [ZJOI2019]线段树(线段树+dp,神仙题)
题面传送门 神仙 ZJOI,不会做啊不会做/kk Sooke:"这八成是考场上最可做的题",由此可见 ZJOI 之毒瘤. 首先有一个非常显然的转化,就是题目中的"将线段树 ...
- 洛谷P5280 [ZJOI2019]线段树(线段树)
题面 传送门 题解 考场上就这么一道会做的其它连暴力都没打--活该爆炸-- 首先我们得看出问题的本质:有\(m\)个操作,总共\(2^m\)种情况分别对应每个操作是否执行,求这\(2^m\)棵线段树上 ...
- 洛谷 P3373 【模板】线段树 2
洛谷 P3373 [模板]线段树 2 洛谷传送门 题目描述 如题,已知一个数列,你需要进行下面三种操作: 将某区间每一个数乘上 xx 将某区间每一个数加上 xx 求出某区间每一个数的和 输入格式 第一 ...
- 洛谷P3372 【模板】线段树 1
P3372 [模板]线段树 1 153通过 525提交 题目提供者HansBug 标签 难度普及+/提高 提交 讨论 题解 最新讨论 [模板]线段树1(AAAAAAAAA- [模板]线段树1 洛谷 ...
- 洛谷P4891 序列(势能线段树)
洛谷题目传送门 闲话 考场上一眼看出这是个毒瘤线段树准备杠题,发现实在太难调了,被各路神犇虐哭qwq 考后看到各种优雅的暴力AC......宝宝心里苦qwq 思路分析 题面里面是一堆乱七八糟的限制和性 ...
- 洛谷 P2574 XOR的艺术(线段树 区间异或 区间求和)
To 洛谷.2574 XOR的艺术 题目描述 AKN觉得第一题太水了,不屑于写第一题,所以他又玩起了新的游戏.在游戏中,他发现,这个游戏的伤害计算有一个规律,规律如下 1. 拥有一个伤害串为长度为n的 ...
- 洛谷P4344 脑洞治疗仪 [SHOI2015] 线段树+二分答案/分块
!!!一道巨恶心的数据结构题,做完当场爆炸:) 首先,如果你用位运算的时候不小心<<打成>>了,你就可以像我一样陷入疯狂的死循环改半个小时 然后,如果你改出来之后忘记把陷入死循 ...
- Bzoj5294/洛谷P4428 [Bjoi2018]二进制(线段树)
题面 Bzoj 洛谷 题解 考虑一个什么样的区间满足重组之后可以变成\(3\)的倍数.不妨设\(tot\)为一个区间内\(1\)的个数.如果\(tot\)是个偶数,则这个区间一定是\(3\)的倍数,接 ...
随机推荐
- MariaDB第三章:数据库设计与备份--小白博客
数据库设计 1.第一范式(确保每列保持原子性) 第一范式是最基本的范式.如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式. 2.第二范式(确保表中的每列都和主键相关) 第 ...
- (PAT)L2-006 树的遍历 (二叉树构建)
题目链接:https://www.patest.cn/contests/gplt/L2-006 给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列.这里假设键值都是互不相等的正整数. 输入格 ...
- 控制结构(6): 最近最少使用(LRU)
// 上一篇:必经之地(using) // 下一篇:程序计数器(PC) 基于语言提供的基本控制结构,更好地组织和表达程序,需要良好的控制结构. There are only two hard thin ...
- Oracle物化视图的创建及使用
oracle物化视图 一.oracle物化视图基本概念 物化视图首先需要创建物化视图日志, oracle依据用户创建的物化视图日志来创建物化视图日志表, 物化视图日志表的名称为mlog$_后面跟 ...
- Unit 3.标签的分类和嵌套规则
一.标签分类 HTML中标签元素三种不同类型:块状元素,行内元素,行内块状元素. 常用的块状元素: <div> <p> <h1>~<h6> <ol ...
- fetch和axios获取数据
fetch("/api/goods") .then(res => { return res.json(); }) .then(response => { console ...
- 记录一下各个用过 IDE 以及 其他工具 的实用快捷键(持续更新)
通用: win10锁屏:win + L win10查看服务:win+R,输入services.msc即可 Shift + Tab:多行缩进 Shift + Space:切换输入法 全/半角 Shift ...
- [NOIp2016] 换教室
题目类型:期望\(DP\) 传送门:>Here< 题意:现有\(N\)个时间段,每个时间段上一节课.如果不申请换教室,那么时间段\(i\)必须去教室\(c[i]\)上课,如果申请换课成功, ...
- consul命令记录
服务端启动脚本 #/bin/bash! echo "********************************************************************* ...
- 洛谷 P1411 树
最近在做些树形DP练练手 原题链接 大意就是给你一棵树,你可以断开任意数量的边,使得剩下的联通块大小乘积最大. 样例 8 1 2 1 3 2 4 2 5 3 6 3 7 6 8 输出 18 我首先想的 ...