题目

区间加,区间乘,单点查询,撤销修改


分析

由于可以离线,不妨把下标看成第一维,时间看成第二维,那么修改操作相当于在一个矩形上加或者乘,

不妨把查询的节点看作是二维平面上的点,这样实际上就可以用 KD-Tree 来实现


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
const int N=150011,mod=998244353;
int ran,n,m,Q,root,ans[N];
struct rec{
int p[2];
bool operator <(const rec &t)const{
return p[ran]<t.p[ran];
}
};
struct Rec{int l,r,z,opt,ed;}q[N];
int mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
void Min(int &x,int y){x=x<y?x:y;}
void Max(int &x,int y){x=x>y?x:y;}
struct KD_Tree{
int mn[N][2],mx[N][2],son[N][2],lazy[N],w[N],tag[N]; rec p[N];
void pup(int now){
mn[now][0]=mx[now][0]=p[now].p[0];
mn[now][1]=mx[now][1]=p[now].p[1];
if (son[now][0]){
Min(mn[now][0],mn[son[now][0]][0]);
Min(mn[now][1],mn[son[now][0]][1]);
Max(mx[now][0],mx[son[now][0]][0]);
Max(mx[now][1],mx[son[now][0]][1]);
}
if (son[now][1]){
Min(mn[now][0],mn[son[now][1]][0]);
Min(mn[now][1],mn[son[now][1]][1]);
Max(mx[now][0],mx[son[now][1]][0]);
Max(mx[now][1],mx[son[now][1]][1]);
}
}
int build(int l,int r,int Ran){
if (l>r) return 0;
int mid=(l+r)>>1;
ran=Ran,nth_element(p+l,p+mid,p+1+r);
son[mid][0]=build(l,mid-1,Ran^1);
son[mid][1]=build(mid+1,r,Ran^1);
tag[mid]=1,pup(mid);
return mid;
}
void ptag(int now,int Tag,int Lazy){
w[now]=mo(1ll*w[now]*Tag%mod,Lazy);
tag[now]=1ll*tag[now]*Tag%mod;
lazy[now]=mo(1ll*lazy[now]*Tag%mod,Lazy);
}
void pdown(int now){
if (son[now][0]) ptag(son[now][0],tag[now],lazy[now]);
if (son[now][1]) ptag(son[now][1],tag[now],lazy[now]);
tag[now]=1,lazy[now]=0;
}
void update(int now,int lx,int rx,int ly,int ry,int opt,int z){
if (mx[now][0]<lx||rx<mn[now][0]||mx[now][1]<ly||ry<mn[now][1]) return;
if (lx<=mn[now][0]&&mx[now][0]<=rx&&ly<=mn[now][1]&&mx[now][1]<=ry){
if (opt==1) ptag(now,1,z);
else ptag(now,z,0);
return;
}
if (lx<=p[now].p[0]&&p[now].p[0]<=rx&&ly<=p[now].p[1]&&p[now].p[1]<=ry){
if (opt==1) w[now]=mo(w[now],z);
else w[now]=1ll*w[now]*z%mod;
}
if (tag[now]!=1||lazy[now]) pdown(now);
if (son[now][0]) update(son[now][0],lx,rx,ly,ry,opt,z);
if (son[now][1]) update(son[now][1],lx,rx,ly,ry,opt,z);
}
void query(int now){
ans[p[now].p[1]]=w[now];
if (tag[now]!=1||lazy[now]) pdown(now);
if (son[now][0]) query(son[now][0]);
if (son[now][1]) query(son[now][1]);
}
}Tre;
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
int main(){
n=iut(),Q=iut();
for (int i=1;i<=Q;++i){
int opt=iut();
if (opt<3){
int l=iut(),r=iut(),z=iut();
if (z>=mod) z-=mod;
q[i]=(Rec){l,r,z,opt,Q};
}else{
int x=iut();
if (opt==3) Tre.p[++m].p[0]=x,Tre.p[m].p[1]=i;
else q[x].ed=i-1,q[i].opt=-1;
}
}
root=Tre.build(1,m,0);
for (int i=1;i<=Q;++i) if (q[i].opt>0)
Tre.update(root,q[i].l,q[i].r,i,q[i].ed,q[i].opt,q[i].z);
Tre.query(root);
for (int i=1;i<=Q;++i) if (!q[i].opt)
print(ans[i]),putchar(10);
return 0;
}

#KD-Tree#洛谷 3710 方方方的数据结构的更多相关文章

  1. 题解 洛谷 P3710 【方方方的数据结构】

    因为有撤销操作,所以修改操作可能会只会存在一段时间,因此把时间看作一维,被修改的序列看作一维. 可以把操作都离线下来,对于每个修改操作,就是在二维平面上对一个矩形进行修改,询问操作,就是查询单点权值. ...

  2. AC日记——【模板】Link Cut Tree 洛谷 P3690

    [模板]Link Cut Tree 思路: LCT模板: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 30 ...

  3. POJ1471 Tree/洛谷P4178 Tree

    Tree P4178 Tree 点分治板子. 点分治就是直接找树的重心进行暴力计算,每次树的深度不会超过子树深度的\(\frac{1}{2}\),计算完就消除影响,找下一个重心. 所以伪代码: voi ...

  4. 洛谷试炼场 提高模板-nlogn数据结构

    树状数组-区间求和 P3374 [模板]树状数组 1 /*by SilverN*/ #include<algorithm> #include<iostream> #includ ...

  5. 洛谷4月月赛R2

    洛谷4月月赛R2 打酱油... A.koishi的数学题  线性筛约数和就可以\(O(N)\)了... #include <iostream> #include <cstdio> ...

  6. 【BZOJ-2648&2716】SJY摆棋子&天使玩偶 KD Tree

    2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2459  Solved: 834[Submit][Status][Discu ...

  7. 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

    洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...

  8. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  9. 洛谷SP16580 QTREE7 - Query on a tree VII(LCT,multiset)

    洛谷题目传送门 思路分析 维护子树最值还是第一次写QwQ 因为子树的最值会变化,所以不能简单地把最值记下来,还要维护一个平衡树,把每个子树的最大值扔进去,来资磁插入.删除和查询最值. 然后我就懒得手写 ...

  10. 洛谷P2633 Count on a tree(主席树上树)

    题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个 ...

随机推荐

  1. Excelize 开源基础发布 2.8.1 版本,2024 年首个更新

    Excelize 是 Go 语言编写的用于操作电子表格办公文档的开源基础库,基于 ISO/IEC 29500.ECMA-376 国际标准.可以使用它来读取.写入由 Microsoft Excel.WP ...

  2. CGI, FastCGI, WSGI, uWSGI, uwsgi一文搞懂

    中间件 1.服务器中间件:nginx,apache 2.数据库中间件:介于应用程序和数据库之前的,MyCat 3.消息队列中间件:kafka,rabbitmq,Rocketmq CGI 1.CGI是一 ...

  3. dotnet nuget的命令行上传(推送/发布)包到Nexus 3

    1.让Visual Studio在生成的时候也生成NuGet的包 在项目上点右键,选"属性",然后设置生成的时候制作NuGet的包. 英文版在这里打勾: 中文版在这里打勾: 重新生 ...

  4. React之父组件向子组件传值

    class Parent extends React.Component{ constructor(){ super(); this.state={co:"red"} } rend ...

  5. Advanced .Net Debugging 3:基本调试任务(上)

    一.简介 这是我的<Advanced .Net Debugging>这个系列的第三篇文章.这个系列的每篇文章写的周期都要很长,因为每篇文章都是原书的一章内容(太长的就会分开写).再者说,原 ...

  6. Sermant运行流程学习笔记,速来抄作业

    本文分享自华为云社区<Sermant 的整体流程学习梳理>,作者:用友汽车信息科技(上海)有限公司 刘亚洲 Java研发工程师. 一.sermant架构 Sermant整体架构包括Serm ...

  7. 并发编程 --- CAS原子操作

    介绍 CAS(Compare And Swap) 是一种无锁算法的实现手段,中文名称为比较并交换.它由 CPU 的原子指令实现,可以在多线程环境下实现无锁的数据结构. 原理 CAS 的原理是:它会先比 ...

  8. 【技术积累】Java 8 新特性

    一.Lambda表达式 Lambda 是一个匿名函数,我们可以把 Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递).可以写出更简洁.更灵活的代码.作为一种更紧凑的代码风格,使J ...

  9. MySql变量说明

    1 #变量 2 /* 3 系统变量: 4 全局变量 5 会话变量 6 7 自定义变量: 8 用户变量 9 局部变量 10 11 */ 12 #一.系统变量 13 /* 14 说明:变量由系统定义,不是 ...

  10. 探究C# dynamic动态类型本质

    本周在做接口动态传参的时候思考了个问题:如何把一个json字符串,转成C#动态类? 比如由 { 'userId': 100, 'id': 1, 'title': 'hello world', 'com ...