题目

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


分析

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

不妨把查询的节点看作是二维平面上的点,这样实际上就可以用 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. java学生管理系统(界面版)

    运行截图 项目说明: 本系统界面我个人就从简设计了,本来打算使用windowbuilder插件设计的,可想到使用windowbuilder插件之后导致代码冗余,会影响到代码可读性,可能对小白不友好.虽 ...

  2. Java Servlet单元测试

    Java Servlet单元测试 1. 解决痛点 虽然目前主流的开发方式,很多都是通过controll或者微服务提供api.但是不免还是需要写几个servlet完成接口开发.按照常规,servlet调 ...

  3. 代码随想录算法训练营第二十七天| 39. 组合总和 40.组合总和II 131.分割回文串

      39. 组合总和 卡哥建议:本题是 集合里元素可以用无数次,那么和组合问题的差别 其实仅在于 startIndex上的控制 题目链接/文章讲解:https://programmercarl.com ...

  4. vscodeC++生成配置文件

    参考 https://www.cnblogs.com/harrypotterisdead/p/14207866.html 和 https://www.cnblogs.com/heyiping/p/14 ...

  5. Java 数组 数据类型默认值

    1 public static void main(String[] args) 2 { 3 int[] arry = new int[4]; //int 默认值0 //浮点型 0.0 4 for(i ...

  6. Educational Codeforces Round 143 (Rated for Div. 2)C. Tea Tasting(前缀和+二分、贡献枚举)

    C. Tea Tasting 思路 这里枚举有三种思路 然后经过考虑3是最可行的,然后接着考虑如何计算贡献 这里在实现的时候用了一个差分数组,因为我们需要记录第i个茶师它喝了多少个\(b_i\)以及不 ...

  7. 微型MPU6050模块及串口/BLE透传的实物展示

    前言   随着时间的积累,项目的沉淀.把很多做过的产品标准化掉,形成可以立即拿出来使用的产品.是非常重要的一个环节.最近,把基于MPU6050的模块微型化并使用串口透传这个产品梳理了一下.形成了标准化 ...

  8. ubuntu中在命令行如何打开图形界面的文件夹的几种方法

    方法一: 使用自带的命令:nautilus . 打开当前文件夹 nautilus . 打开指定路径文件夹 nautilus ddd/ccc/ 方法二:xdg-open xdg-open 命令相当于在 ...

  9. 定义pod的hosts文件(HostAliases)

    通过HostAliases 向 Pod /etc/hosts 文件添加条目 当 DNS 配置以及其它选项不合理的时候,通过向 Pod 的 /etc/hosts 文件中添加条目, 可以在 Pod 级别覆 ...

  10. 对TCP/IP协议的理解

    话说两台电脑要通讯就必须遵守共同的规则,就好比两个人要沟通就必须使用共同的语言一样.一个只懂英语的人,和一个只懂中文的人由于没有共同的语言(规则)就没办法沟通.两台电脑之间进行通讯所共同遵守的规则,就 ...