• 【CF575I】Robots protection(二维树状数组)


    点此看题面

    • 有一张(n imes n)的二维平面。
    • (q)次操作,分为两种:摆放一个两直角边平行于坐标轴的等腰直角三角形;询问一个点被多少三角形覆盖。
    • (nle5 imes10^3,qle10^5)

    二维树状数组

    以斜边在左上方的直角三角形为例(可以通过每次将整个二维平面旋转(90^circ)把四种直角三角形都化为这种情况)。

    假设它的顶点坐标是((x,y)),边长是(l),那么被它覆盖的点((X,Y))就需要满足:(X+Yle x+y+l)(Xge x)(Yge y)

    此时我们可以直接用树套树套树解决此题。

    考虑我们修改一下条件,添上(X+Yge x+y)这个必要条件,则(Xge x)(Yge y)最多只有一个不满足。

    因此我们容斥,给所有满足(x+yle X+Yle x+y+l)的点加(1),再给满足这个条件的前提下所有(X<x)(Y<y)的点分别减(1)

    这样一来只需要一个树状数组和两个二维树状数组就解决了此题。

    代码:(O(qlog^2n))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 5000
    #define M 100000
    using namespace std;
    int n,Qt,ans[M+5];struct OP {int op,x,y,d,l;}q[M+5];
    namespace FastIO
    {
    	#define FS 100000
    	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    	#define pc(c) (FC==FE&&(clear(),0),*FC++=c)
    	int OT;char oc,FI[FS],FO[FS],OS[FS],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
    	I void clear() {fwrite(FO,1,FC-FO,stdout),FC=FO;}
    	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
    	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    	Tp I void writeln(Ty x) {W(OS[++OT]=x%10+48,x/=10);W(OT) pc(OS[OT--]);pc('
    ');}
    }using namespace FastIO;
    struct TreeArray//树状数组
    {
    	int a[2*N+5];I void Cl() {for(RI i=0;i<=2*n;++i) a[i]=0;}
    	I void U_(RI x,CI v) {W(x<=2*n) a[x]+=v,x+=x&-x;}I void U(CI x,CI y) {U_(x,1),U_(y+1,-1);}
    	I int Q(RI x,RI t=0) {W(x) t+=a[x],x-=x&-x;return t;}
    }T;
    struct TreeArray2//二维树状数组
    {
    	int a[2*N+5][N+5];I void Cl() {for(RI i=0;i<=2*n;++i) for(RI j=0;j<=n;++j) a[i][j]=0;}
    	I void U1(int* a,RI x,RI v) {W(x) a[x]+=v,x-=x&-x;}
    	I void U2(RI x,CI y,CI v) {W(x<=2*n) U1(a[x],y,v),x+=x&-x;}
    	I void U(CI x1,CI x2,CI y) {U2(x1,y,1),U2(x2+1,y,-1);}
    	I int Q(int* a,RI x,RI t=0) {W(x<=n) t+=a[x],x+=x&-x;return t;}
    	I int Q(RI x,CI y,RI t=0) {W(x) t+=Q(a[x],y),x-=x&-x;return t;}
    }X,Y;
    int main()
    {
    	RI i;for(read(n,Qt),i=1;i<=Qt;++i) read(q[i].op),
    		q[i].op==1?(read(q[i].d,q[i].x,q[i].y,q[i].l),q[i].d>2&&(q[i].d=7-q[i].d)):(read(q[i].x,q[i].y),0);//交换3,4类型,方便旋转
    	for(RI D=1,l,r;D<=4;++D) for(T.Cl(),X.Cl(),Y.Cl(),i=1;i<=Qt;swap(q[i].x,q[i].y),q[i].x=n-q[i].x+1,++i)//枚举类型,每次将所有点旋转90°
    		q[i].op==1&&q[i].d==D&&(T.U(l=q[i].x+q[i].y,r=q[i].x+q[i].y+q[i].l),X.U(l,r,q[i].x-1),Y.U(l,r,q[i].y-1),0),//放置这种类型的三角形
    		q[i].op==2&&(ans[i]+=T.Q(q[i].x+q[i].y)-X.Q(q[i].x+q[i].y,q[i].x)-Y.Q(q[i].x+q[i].y,q[i].y));//询问,用总情况减去两种不合法情况
    	for(i=1;i<=Qt;++i) q[i].op==2&&(writeln(ans[i]),0);return clear(),0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    ps-- 制作磨砂背景
    ps -- 证件照
    抠图--薄,透
    60后发送短信的方法
    小项目 -- 验证码.js
    小项目
    小项目 -- phone.js
    基于GDAL提取地物,并生成png,最后加载到网页上(二)
    根据范围获取影像瓦片,并生成GeoTIFF 文件《一》
    Ubuntu 10.4 +NVIDIA GTX 1070 显卡驱动更新
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF575I.html
Copyright © 2020-2023  润新知