洛谷题面传送门

首先显然原问题严格强于区间数颜色,因此考虑将询问离线下来然后用某些根号级别复杂度的数据结构。按照数颜色题目的套路,我们肯定要对于每种颜色维护一个前驱 \(pre\),那么答案可写作 \(pre\ge l\) 的所有颜色的权值之和。此题也不例外。考虑将所有询问存在右端点,那么每次扫描一个矩形 \(i\),就将矩形中所有点被覆盖的时间设为 \(i\),那么 \([l,r]\) 区间的答案即为扫描到 \(r\) 时 \(pre\ge l\) 的点权之和。

考虑怎么维护 \(pre\),首先看到矩形以及这个 128M 的空间,显然不是让我们树套树而是让我们 2-DT 的,因此建出 2-DT,那么矩形覆盖即可转化为 \(\mathcal O(\sqrt{n})\) 个单点修改和 \(\mathcal O(\sqrt{n})\) 个子树整体修改,但是由于我们并不是简简单单地求出 \(pre\) 就完事了,我们还要求出 \(pre\) 值在一段区间内的点权之和,事情变得棘手起来……不过注意到这样一件事,对于单点修改显然如果原来有标记那就直接撤销贡献即可,对于子树整体修改,整体覆盖的点的子树都是不交的,而撤销贡献等价于“收回”标记,即打标记的逆操作。因此我们考虑对一个子树整体覆盖时,就暴力 DFS 整棵子树收回子树中所有标记,如果子树中没有标记那就 return,然后假设我们欲将矩形中所有点赋值为 \(v\),那么我们就建立一个数据结构并在这个数据结构下标为 \(v\) 的位置加上当前子树中所有点点权和。由于收回标记是打标记的逆操作,你暴力 DFS 的复杂度均摊下来肯定和打标记相同,因此这部分复杂度是 \(m\sqrt{n}\) 的。

接下来考虑怎样计算答案,通过上面的分析我们已经能够在较快时间内维护 \(pre\) 为某个值的点权之和的变化了,这样扫描到 \(r\) 时,我们只需做一遍区间求和即可求出区间 \([l,r]\) 的答案。那么用什么数据结构维护呢?根据根号平衡的思想,如果用树状数组那么复杂度 \(m\sqrt{n}\log n+q\log n\),导致复杂度向左倾,不知道能不能过。换成 \(\mathcal O(1)\) 单点加 \(\mathcal O(\sqrt{n})\) 求和的分块复杂度就是 \(m\sqrt{n}+q\sqrt{m}\),应该就比较稳了(

const int MAXN=1e5;
const int K=2;
const int BLK=317;
const int MAXQ=1e6;
int n,m,qu;
struct point{
int x[K+2],v;
point(){memset(x,0,sizeof(x));v=0;}
int& operator [](int id){return x[id];}
} p[MAXN+5];
struct node{int ch[2],tg,has_tag,tg_pt;ll sum;point val,mn,mx;} s[MAXN+5];
void pushup0(int k){s[k].sum=s[s[k].ch[0]].sum+s[s[k].ch[1]].sum+s[k].val.v;}
void pushup(int k){s[k].has_tag=s[s[k].ch[0]].has_tag|s[s[k].ch[1]].has_tag|(s[k].tg>0)|(s[k].tg_pt>0);}
int ncnt=0,rt=0;
void build(int &k,int l,int r){
if(l>r) return;k=++ncnt;
static double avg[K+2],var[K+2];
fill(avg,avg+K,0);fill(var,var+K,0);
for(int i=l;i<=r;i++) for(int j=0;j<K;j++) avg[j]+=p[i][j];
for(int j=0;j<K;j++) avg[j]/=(r-l+1);
for(int i=l;i<=r;i++) for(int j=0;j<K;j++) var[j]+=(p[i][j]-avg[j])*(p[i][j]-avg[j]);
double mx=0;int dim=0;
for(int j=0;j<K;j++) if(var[j]>mx) mx=var[j],dim=j;
int mid=l+r>>1;nth_element(p+l,p+mid,p+r+1,[&](point x,point y){return x[dim]<y[dim];});
build(s[k].ch[0],l,mid-1);build(s[k].ch[1],mid+1,r);
s[k].val=s[k].mn=s[k].mx=p[mid];
// printf("node %d %d %d %d\n",k,p[mid][0],p[mid][1],p[mid].v);
// printf("%d %d %d\n",k,s[k].ch[0],s[k].ch[1]);
for(int j=0;j<K;j++){
if(s[k].ch[0]) chkmin(s[k].mn[j],s[s[k].ch[0]].mn[j]),chkmax(s[k].mx[j],s[s[k].ch[0]].mx[j]);
if(s[k].ch[1]) chkmin(s[k].mn[j],s[s[k].ch[1]].mn[j]),chkmax(s[k].mx[j],s[s[k].ch[1]].mx[j]);
} pushup0(k);
}
struct blk_ds{
ll blk_sum[BLK+5],val[MAXN+5];
int blk_cnt,blk_sz,bel[MAXN+5],L[BLK+5],R[BLK+5];
void init(){
blk_sz=(int)sqrt(m);blk_cnt=(m-1)/blk_sz+1;
for(int i=1;i<=blk_cnt;i++){
L[i]=(i-1)*blk_sz+1;R[i]=min(i*blk_sz,m);
for(int j=L[i];j<=R[i];j++) bel[j]=i;
}
}
void add(int x,ll v){/*printf("add %d %lld\n",x,v);*/blk_sum[bel[x]]+=v;val[x]+=v;}
ll query(int l,int r){
if(bel[l]==bel[r]){
ll sum=0;
for(int i=l;i<=r;i++) sum+=val[i];
return sum;
} else {
ll sum=0;
for(int i=l;i<=R[bel[l]];i++) sum+=val[i];
for(int i=bel[l]+1;i<bel[r];i++) sum+=blk_sum[i];
for(int i=L[bel[r]];i<=r;i++) sum+=val[i];
return sum;
}
}
} B;
struct bar{int x1,y1,x2,y2;} b[MAXN+5];
vector<pii> qv[MAXN+5];
ll res[MAXQ+5];
bool dfscheck(int k);
void clrtag(int k){
if(!s[k].has_tag||!k) return;
if(s[k].tg) B.add(s[k].tg,-s[k].sum),s[k].tg=0;
if(s[k].tg_pt) B.add(s[k].tg_pt,-s[k].val.v),s[k].tg_pt=0;
clrtag(s[k].ch[0]);clrtag(s[k].ch[1]);s[k].has_tag=0;
}
void pushdown(int k){
if(s[k].tg){
if(s[k].ch[0]) s[s[k].ch[0]].tg=s[k].tg;
if(s[k].ch[1]) s[s[k].ch[1]].tg=s[k].tg;
s[k].tg_pt=s[k].tg;s[k].tg=0;
s[s[k].ch[0]].has_tag=s[s[k].ch[1]].has_tag=1;
}
}
//bool dfscheck(int k){
// if(!k) return 0;
// bool ok=dfscheck(s[k].ch[0])|dfscheck(s[k].ch[1]);
// if(ok&&s[k].tg) exit(1);
// return ok|(s[k].tg>0)|(s[k].tg_pt>0);
//}
void pushtag(int k,int x1,int y1,int x2,int y2,int v){
if(!k) return;
if(s[k].mx[0]<x1||s[k].mn[0]>x2||s[k].mx[1]<y1||s[k].mn[1]>y2) return;
pushdown(k);
if(x1<=s[k].mn[0]&&s[k].mx[0]<=x2&&y1<=s[k].mn[1]&&s[k].mx[1]<=y2){
clrtag(k);B.add(v,s[k].sum);s[k].tg=v;pushup(k);return;
}
if(x1<=s[k].val[0]&&s[k].val[0]<=x2&&y1<=s[k].val[1]&&s[k].val[1]<=y2){
if(s[k].tg_pt) /*printf("!!! %d ",s[k].val[0]),*/B.add(s[k].tg_pt,-s[k].val.v);
s[k].tg_pt=v;/*printf("!!! %d ",s[k].val[0]);*/B.add(s[k].tg_pt,s[k].val.v);
} pushtag(s[k].ch[0],x1,y1,x2,y2,v);pushtag(s[k].ch[1],x1,y1,x2,y2,v);
pushup(k);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&p[i][1],&p[i].v),p[i][0]=i;
scanf("%d",&m);for(int i=1;i<=m;i++) scanf("%d%d%d%d",&b[i].x1,&b[i].x2,&b[i].y1,&b[i].y2);//pay attention to the sequence of input
scanf("%d",&qu);for(int i=1,l,r;i<=qu;i++) scanf("%d%d",&l,&r),qv[r].pb(mp(l,i));
build(rt,1,n);B.init();
for(int i=1;i<=m;i++){
pushtag(rt,b[i].x1,b[i].y1,b[i].x2,b[i].y2,i);
for(pii p:qv[i]) res[p.se]=B.query(p.fi,i);
// dfscheck(rt);
}
for(int i=1;i<=qu;i++) printf("%lld\n",res[i]);
return 0;
}

欸,貌似再下一个题号就是我们月赛的题了呢

洛谷 P6783 - [Ynoi2008] rrusq(KDT+势能均摊+根号平衡)的更多相关文章

  1. 题解 洛谷 P3396 【哈希冲突】(根号分治)

    根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...

  2. bzoj5312: 冒险(势能均摊线段树)

    题目链接 BZOJ5312: 冒险 题解 如果一次操作对区间& 和 区间| 产生的影响是相同的,那么该操作对整个区间的影响都是相同的 对于每次操作,在某些位上的值,对于整个区间影响是相同的,对 ...

  3. 洛谷 P6349 - [PA2011]Kangaroos(KDT+标记下放)

    洛谷题面传送门 KDT 上打标记的 hot tea. 考虑将询问 \(A,B\) 看作二维平面直角坐标系上的一个点 \((A,B)\),那么我们这样考虑,我们从左到右扫过全部 \(n\) 个区间并开一 ...

  4. 洛谷P4891 序列(势能线段树)

    洛谷题目传送门 闲话 考场上一眼看出这是个毒瘤线段树准备杠题,发现实在太难调了,被各路神犇虐哭qwq 考后看到各种优雅的暴力AC......宝宝心里苦qwq 思路分析 题面里面是一堆乱七八糟的限制和性 ...

  5. 洛谷P1337 【[JSOI2004]平衡点 / 吊打XXX】(模拟退火)

    洛谷题目传送门 很可惜,充满Mo力的Mo拟退火并不是正解.不过这是一道最适合开始入手Mo拟退火的好题. 对模拟退火还不是很清楚的可以看一下 这道题还真和能量有点关系.达到平衡稳态的时候,物体的总能量应 ...

  6. 洛谷P1198 [JSOI2008]最大数

    P1198 [JSOI2008]最大数 267通过 1.2K提交 题目提供者该用户不存在 标签线段树各省省选 难度提高+/省选- 提交该题 讨论 题解 记录 最新讨论 WA80的戳这QwQ BZOJ都 ...

  7. 关于三目运算符与if语句的效率与洛谷P2704题解

    题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图.在每一格平原地形上最 ...

  8. 洛谷P1126 机器人搬重物

    洛谷1126 机器人搬重物 题目描述 机器人移动学会(RMI)现在正尝试用机器人搬运物品.机器人的形状是一个直径1.6米的球.在试验阶段,机器人被用于在一个储藏室中搬运货物.储藏室是一个N*M的网格, ...

  9. 洛谷 P3384 【模板】树链剖分

    树链剖分 将一棵树的每个节点到它所有子节点中子树和(所包含的点的个数)最大的那个子节点的这条边标记为"重边". 将其他的边标记为"轻边". 若果一个非根节点的子 ...

随机推荐

  1. 全场景效能平台猪齿鱼常用的前端css实现方案

    ​ 居中 最常用的height + line-height,以及margin:0 auto的居中方式就不再阐述,以下介绍两种容错性高的实现方案. flex布局实现 ​ 猪齿鱼前端日常开发中,我们多以f ...

  2. 小白自制Linux开发板 七. USB驱动配置

    本文章基于https://whycan.com/t_3087.htmlhttps://whycan.com/t_6021.html整理 F1c100s芯片支持USB的OTG模式,也就是可以通过更改Us ...

  3. [软工顶级理解组] Beta阶段测试报告

    在测试过程中发现了多少Bug? 测试阶段发现并已修复的bug: 尚且存在,但是难以解决或者不影响使用的bug: 计算重修课程的时候,如果重修课程的课程号和原课程号不同,则GPA计算会出现误差.但我们无 ...

  4. 【二食堂】Alpha - 项目展示

    项目展示 1. 团队介绍 二食堂很难排队 姓名 介绍 职务 刘享 热爱游戏,尤其是RPG和metrovinia类的游戏. 会C/C++, python, java. 后端 左正 一个普通的大学生,Py ...

  5. 2021.7.17 NKOJ周赛总结

    发现自己简直是个智障:T1模数写成1e9+9:T2居然没有考虑刚好一个周期的情况:T4用"%lld"读入"unsigned long long".~qwq~ T ...

  6. 【做题记录】CF1444A Division

    CF1444A Division 题意: 给定 \(t\) 组询问,每组给两个数 \(p_i\) 和 \(q_i\) ,找出最大的整数 \(x_i\) ,要求 \(p_i\) 可被 \(x_i\) 整 ...

  7. 验证人员应该以何种角度阅读spec

    转载:验证人员应该以何种角度阅读spec - 微波EDA网 (mweda.com) 在开发流程中,设计和验证人员关注的点肯定是不一样的,尤其在spec的理解上,验证人员往往需要有自己独立的理解.在拿到 ...

  8. no space left on device 磁盘空间不足

    新挂载的目录,创建文件提示:no space left on device 1.执行命令:df -h ,查看盘是否挂载成功 2.用history命令查看历史命令,尴尬的发现挂载前忘记格式化了 3.取消 ...

  9. 使用getopt 解析参数

    getopt被用来解析命令行选项参数. #include <unistd.h> extern char *optarg; //选项的参数指针 extern int optind, //下一 ...

  10. 关于JDBC中查询方法的抽取

    萌新的JAVA学习笔记[1] 先来张伊蕾娜镇场~~ 简单描述 起初我们的查询方法时分为单个查询和全部查询,过于局限与繁琐,如此一来我们能不能想一个办法将所有类型的查询抽取出来并整合成为一个单独的工具方 ...