标签:数据结构 struct 标记 int 选讲 sqrt 矩形 include lxl
rrusq
题目描述
解法
考虑扫描矩形的右端点,维护所有左端点的答案。
考虑加入一个矩形的影响,可以用染色模型来理解,也就是把在这个矩形内的点染成这个矩形编号的颜色,那么查询只需要找颜色 \(\geq l\) 的点权值和即可。
考虑如何快速染色并且维护点权,一个显然的想法是颜色段均摊,因为本题是二维意义下的,所以我们可以在 \(\tt kdt\) 上颜色段均摊。具体来说就是在给一个点打标记时,直接暴力清空在子树中的标记,颜色标记需要在递归前下传。
打标记时可以拿一个全局的数据结构来支持修改和点权查询,我们可以使用 \(O(1)-O(\sqrt n)\) 的分块技术。
注意本题操作的特殊性,\(\tt kdt\) 要类似线段树来建立(非叶节点代表区间,不代表实际的点);复杂度基于,对于每个矩形打标记的时间和删除标记的时间是一样的,所以总时间复杂度 \(O(m\sqrt n+q\sqrt m)\)
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int M = 100005;
const int Z = M<<2;
const int N = 1000005;
const int inf = 0x3f3f3f3f;
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
void write(int x)
{
if(x>=10) write(x/10);
putchar(x%10+'0');
}
int n,m,q,A[Z],B[Z],C[Z],D[Z];
int xl,xr,yl,yr,s[Z],col[Z],vis[Z];
struct node{int x,y,v;}a[M];vector<int> v[M];
struct hhz{int a,b,c,d;}t[M];int ans[N],L[N];
struct zxy
{
int n,a[M],b[M],fl[M],L[M],R[M];
void init()
{
int m=sqrt(n);
for(int i=1;i<=n;i++)
{
b[i]=(i-1)/m+1;
if(!L[b[i]]) L[b[i]]=i;
R[b[i]]=i;
}
}
void add(int x,int y) {a[x]+=y;fl[b[x]]+=y;}
int ask(int x)
{
int r=0;
for(int i=b[x]+1;i<=b[n];i++) r+=fl[i];
for(int i=x;i<=R[b[x]];i++) r+=a[i];
return r;
}
}H;
void build(int x,int l,int r,int w)
{
if(l==r)
{
s[x]=a[l].v;
A[x]=B[x]=a[l].x;
C[x]=D[x]=a[l].y;
return ;
}
int mid=(l+r)>>1;
nth_element(a+l,a+mid,a+1+r,[&](node u,node v)
{return w==0?(u.x<v.x):(u.y<v.y);});
build(x<<1,l,mid,w^1);
build(x<<1|1,mid+1,r,w^1);
A[x]=min(A[x<<1],A[x<<1|1]);
B[x]=max(B[x<<1],B[x<<1|1]);
C[x]=min(C[x<<1],C[x<<1|1]);
D[x]=max(D[x<<1],D[x<<1|1]);
s[x]=s[x<<1]+s[x<<1|1];
}
int out(int x)
{
return A[x]>xr || B[x]<xl || C[x]>yr || D[x]<yl;
}
int in(int x)
{
return xl<=A[x] && B[x]<=xr && yl<=C[x] && D[x]<=yr;
}
void down(int x)
{
if(!col[x]) return ;
col[x<<1]=col[x<<1|1]=col[x];
vis[x<<1]=vis[x<<1|1]=1;col[x]=0;
}
void clr(int x)
{
if(!vis[x]) return ;vis[x]=0;
if(col[x])
{
H.add(col[x],-s[x]);
col[x]=0;return ;
}
clr(x<<1);clr(x<<1|1);
}
void dfs(int x,int y)
{
if(out(x)) return ;
if(in(x))
{
clr(x);col[x]=y;vis[x]=1;
H.add(y,s[x]);return ;
}
down(x);dfs(x<<1,y);dfs(x<<1|1,y);
vis[x]=1;
}
signed main()
{
n=read();A[0]=C[0]=inf;
for(int i=1;i<=n;i++)
a[i].x=i,a[i].y=read(),a[i].v=read();
build(1,1,n,0);
m=read();H.n=m;H.init();
for(int i=1;i<=m;i++)
t[i].a=read(),t[i].b=read(),
t[i].c=read(),t[i].d=read();
q=read();
for(int i=1;i<=q;i++)
L[i]=read(),v[read()].push_back(i);
for(int i=1;i<=m;i++)
{
xl=t[i].a;xr=t[i].b;
yl=t[i].c;yr=t[i].d;
dfs(1,i);
for(int x:v[i]) ans[x]=H.ask(L[x]);
}
for(int i=1;i<=q;i++)
write(ans[i]),puts("");
}
标签:数据结构,struct,标记,int,选讲,sqrt,矩形,include,lxl 来源: https://www.cnblogs.com/C202044zxy/p/16422164.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。