题目:http://acm.hdu.edu.cn/showproblem.php?pid=5283
思路:这题的离线做法非常简单不必多说,我想说的是在线做法。。。因为我太傻逼一开始没有意识到这是个离线问题。
在线的话就是分块,我们进行序列分块,对横纵坐标分开维护,注意到一个点只会进出一次,就拿横坐标举例,我们使块内有序,维护一个块的指针
L
和
代码因为边界调的我意识模糊。。。
复杂度:
O(nn√)
代码:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
//#include<cmath>
#define N 100002
#define M 502
using namespace std;
int n,m,x[N],y[N],Xtag[M],Ytag[M],XL[M],XR[M],YL[M],YR[M],num[M],l,r,d,
belong[N],bl[M],br[M],XID[N],YID[N],ll,rr,Q[N],x1,x2,y1,y2,B,cnt,tm;
bool in[N];
//对每个块,tag[i]表示块i的标记,L[i]表示出现点,R[i]表示消失点
//分别按x,y维护,再实时维护一个没有标记的坐标,num[i]表示块i的和
//belong = (i - 1) / B
inline void ino(int &xx)
{
char c; int sy = 1;
while (!isdigit(c = getchar()))
if (c == '-') sy = -1;
xx = (c ^ 48);
while (isdigit(c = getchar())) xx = 10 * xx + (c ^ 48);
xx *= sy;
}
inline bool cmp1(int a,int b)
{
return x[a] < x[b];
}
inline bool cmp2(int a,int b)
{
return y[a] < y[b];
}
inline void X_rebuild(int i)
{
int j;
Xtag[i] = 0; num[i] = 0;
j = bl[i];
for (;j <= br[i]&&x[XID[j]] < x1; ++j);
XL[i] = j;
j = br[i];
for (;j >= bl[i]&&x[XID[j]] > x2; --j);
XR[i] = j;
for (j = bl[i];j <= br[i]; ++j)
{
if (x[j] >= x1&&x[j] <= x2&&y[j] >= y1&&y[j] <= y2) in[j] = 1,num[i]++;
else in[j] = 0;
}
}
inline void Y_rebuild(int i)
{
int j;
Ytag[i] = 0; num[i] = 0;
j = bl[i];
for (;j <= br[i]&&y[YID[j]] < y1; ++j);
YL[i] = j;
j = br[i];
for (;j >= bl[i]&&y[YID[j]] > y2; --j);
YR[i] = j;
for (int j = bl[i];j <= br[i]; ++j)
if (x[j] >= x1&&x[j] <= x2&&y[j] >= y1&&y[j] <= y2) in[j] = 1,num[i]++;
else in[j] = 0;
}
inline void init()
{
ino(n);
ino(x1); ino(y1); ino(x2); ino(y2);
for (int i = 1;i <= n; ++i) ino(x[i]),ino(y[i]);
for (B = 1;B * B <= n; ++B);
for (int i = 1;i <= n;++i) belong[i] = (i - 1) / B;
belong[n + 1] = n / B + 1;
memset(Xtag,0,sizeof(Xtag));
memset(Ytag,0,sizeof(Ytag));
memset(in,0,sizeof(in));
belong[0] = -1;
for (int i = 1;i <= n; ++i)
{
if (belong[i] != belong[i - 1]) bl[belong[i]] = i;
if (belong[i] != belong[i + 1]) br[belong[i]] = i;
}
cnt = (n - 1) / B;
for (int i = 1;i <= n; ++i) XID[i] = i,YID[i] = i;
for (int i = 0;i <= cnt; ++i)
{
sort(XID + bl[i],XID + br[i] + 1,cmp1);
sort(YID + bl[i],YID + br[i] + 1,cmp2);
X_rebuild(i);
Y_rebuild(i);
}
}
inline bool pd(int P,int al,int ar)
{
return (P >= al&&P <= ar);
}
inline void X_merge(int blo,int lo,int ro)
{
for (int i = bl[blo];i <= br[blo]; ++i) x[XID[i]] += Xtag[blo] + (pd(XID[i],lo,ro) ? d : 0),y[YID[i]] += Ytag[blo];
Xtag[blo] = 0; Ytag[blo] = 0;
int p = bl[blo],q = bl[blo];
for (;p <= br[blo]&&!pd(XID[p],lo,ro);++p);
for (;q <= br[blo]&&pd(XID[q],lo,ro);++q);
for (int i = bl[blo];i <= br[blo]; ++i)
{
if (q > br[blo]||p <= br[blo]&&x[XID[p]] < x[XID[q]])
{
Q[i] = XID[p++];
for (;p <= br[blo]&&!pd(XID[p],lo,ro); ++p);
}
else
{
Q[i] = XID[q++];
for (;q <= br[blo]&&pd(XID[q],lo,ro); ++q);
}
}
for (int i = bl[blo];i <= br[blo]; ++i) XID[i] = Q[i];
}
inline void X_Deal_middle()
{
for (int i = ll + 1;i < rr; ++i)
{
Xtag[i] += d;
int j;
for (j = XR[i];j >= bl[i]&&x[XID[j]] + Xtag[i] > x2; --j)
if (in[XID[j]]) --num[i],in[XID[j]] = 0;
XR[i] = j;
for (j = XL[i] - 1;j >= bl[i]&&x[XID[j]] + Xtag[i] >= x1; --j)
if (y[XID[j]] + Ytag[i] <= y2&&y[XID[j]] + Ytag[i] >= y1&&x[XID[j]] + Xtag[i] <= x2&&!in[XID[j]]) ++num[i],in[XID[j]] = 1;
XL[i] = j + 1;
}
}
inline void X_()
{
ino(d);
ll = belong[l]; rr = belong[r];
X_Deal_middle();
if (ll != rr)
{
X_merge(ll,l,br[ll]);
X_rebuild(ll);
X_merge(rr,bl[rr],r);
X_rebuild(rr);
}
else
{
X_merge(ll,l,r);
X_rebuild(ll);
}
}
inline void Y_Deal_middle()
{
for (int i = ll + 1;i < rr; ++i)
{
Ytag[i] += d;
int j;
for (j = YR[i];j >= bl[i]&&y[YID[j]] + Ytag[i] > y2; --j)
{
if (in[YID[j]]) --num[i],in[YID[j]] = 0;}
YR[i] = j;
for (j = YL[i] - 1;j >= bl[i]&&y[YID[j]] + Ytag[i] >= y1; --j)
if (x[YID[j]] + Xtag[i] <= x2&&x[YID[j]] + Xtag[i] >= x1&&y[YID[j]] + Ytag[i] <= y2&&!in[YID[j]]) ++num[i],in[YID[j]] = 1;
YL[i] = j + 1;
}
}
void Y_merge(int blo,int lo,int ro)
{
for (int i = bl[blo];i <= br[blo]; ++i) y[YID[i]] += Ytag[blo] + (pd(YID[i],lo,ro) ? d : 0),x[XID[i]] += Xtag[blo];
Ytag[blo] = 0; Xtag[blo] = 0;
int p = bl[blo],q = bl[blo];
for (;p <= br[blo]&&!pd(YID[p],lo,ro);++p);
for (;q <= br[blo]&&pd(YID[q],lo,ro);++q);
for (int i = bl[blo];i <= br[blo]; ++i)
{
if (q > br[blo]||p <= br[blo]&&y[YID[p]] < y[YID[q]])
{
Q[i] = YID[p++];
for (;p <= br[blo]&&!pd(YID[p],lo,ro); ++p);
}
else
{
Q[i] = YID[q++];
for (;q <= br[blo]&&pd(YID[q],lo,ro); ++q);
}
}
for (int i = bl[blo];i <= br[blo]; ++i) YID[i] = Q[i];
}
inline void Y_()
{
ino(d);
ll = belong[l]; rr = belong[r];
Y_Deal_middle();
if (ll != rr)
{
Y_merge(ll,l,br[ll]);
Y_rebuild(ll);
Y_merge(rr,bl[rr],r);
Y_rebuild(rr);
}
else
{
Y_merge(ll,l,r);
Y_rebuild(ll);
}
}
inline void Q_()
{
int S = 0;
int ll = belong[l],rr = belong[r];
for (int i = ll + 1;i < rr; ++i) S += num[i];
if (ll == rr)
for (int i = l;i <= r; ++i) S += in[i];
else
{
int t = br[belong[l]];
for (int i = l;i <= t; ++i) S += in[i];
t = bl[belong[r]];
for (int i = r;i >= t; --i) S += in[i];
}
printf("%d\n",S);
}
inline void DO_IT()
{
int ty;
ino(m);
tm = 0;
for (;m;--m)
{
ino(ty); ino(l); ino(r);
if (ty == 1) X_();
if (ty == 2) Y_();
if (ty == 3) Q_();
}
}
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w",stdout);
init();
DO_IT();
fclose(stdin); fclose(stdout);
return 0;
}
/*
5
1 1 5 5
1 1
2 2
3 3
4 4
5 5
3
3 1 5
1 2 4 2
3 1 5
*/
总结: