Description
火神最爱的就是吃鱼了,所以某一天他来到了一个池塘边捕鱼。池塘可以看成一个二维的平面,而他的渔网可以看成一个与坐标轴平行的矩形。
池塘里的鱼不停地在水中游动,可以看成一些点。有的时候会有鱼游进渔网,有的时候也会有鱼游出渔网。所以火神不知道什么时候收网才可以抓住最多的鱼,现在他寻求你的帮助。
他对池塘里的每条鱼都给予了一个标号,分别从1到n标号,n表示池塘里鱼的总数。鱼的游动可以概括为两个动作:
1 l r d : 表示标号在[l,r]这个区间内的鱼向x轴正方向游动了d个单位长度。
2 l r d:表示标号在[l,r]这个区间内的鱼向y轴正方向游动了d个单位长度。
在某些时刻火神会询问你现在有多少条他关心的鱼在渔网内(边界上的也算),请你来帮助他吧。
Input
第一行包含一个整数T,表示测试数据组数。
对于每组测试数据:
第一行包含一个整数n表示鱼的总数。
第二行包含四个整数x1,y1,x2,y2,表示渔网的左下角坐标和右上角坐标。
接下来n行每行两个整数xi,yi,表示标号为i的鱼初始时刻的坐标。
接下来一行包含一个整数m,表示后面的事件数目。
接下来的mm行每行为以下三种类型的一种:
1 l r d : 表示标号在[l,r]这个区间内的鱼向x轴正方向游动了d个单位长度。
2 l r d:表示标号在[l,r]这个区间内的鱼向y轴正方向游动了d个单位长度。
3 l r : 表示询问现在标号在[l,r]这个区间内的鱼有多少在渔网内。
Output
对于每组数据的每个询问,输出一个整数表示对应的答案。
Sample Input
1
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
Sample Output
5
4
Data Constraint
对于30%的数据1≤n,m≤1000
对于100%的数据1≤T≤10,1≤n,m≤30000,1≤l≤r≤n. 1≤d≤10^9,x1≤x2,y1≤y2。保证任意时刻所有涉及的坐标值在[−10^9,10^9]范围内。
Solution
有一个重要条件:游动的距离是正数,意味着一条鱼最多是从外面游进网里然后再游出去,而网是不会动的,那就分别维护每条鱼的横坐标和纵坐标是否在网内,并维护答案即可
只讨论x轴,Y轴是一样的。
维护在第一条线的左边mi和第二条线的左边ma的最大值,每次操作后如果mi>x1或ma>x2那就非法了,然后去修改并维护答案,在维护答案的时候注意,如果x坐标是合法的,那还要判断y坐标也是合法的。
打的时候所有关于线段树的东西都复制一遍就行了
码农是必须的了
Code
#include<cstdio>
#include<cstring>
#define fo(i,a,b) for(ll i=a;i<=b;i++)
#define N 30100
#define INF -214748364721311121ll
#define ll long long
using namespace std;
int ac,n;
ll an,x1,y1,x2,y2,a[N][3];
struct note{
ll l,mi,ma;
};
note t[N*50],t1[N*50];
ll ans[N*50];
ll max(ll a,ll b){
return a>b?a:b;}
void build(int v,int i,int j)
{
if(i==j)
{
t[v].mi=t[v].ma=INF;t[v].l=0;
if(a[i][1]<=x2) if(a[i][1]<x1) t[v].mi=a[i][1];else t[v].ma=a[i][1];
t1[v].mi=t1[v].ma=INF;t1[v].l=0;
if(a[i][2]<=y2) if(a[i][2]<y1) t1[v].mi=a[i][2];else t1[v].ma=a[i][2];
if(a[i][1]>=x1&&a[i][2]>=y1&&a[i][1]<=x2&&a[i][2]<=y2) ans[v]=1;else ans[v]=0;
return;
}
int m=(i+j)/2;build(v*2,i,m);build(v*2+1,m+1,j);ans[v]=ans[v*2]+ans[v*2+1];
t[v].mi=max(t[v*2].mi,t[v*2+1].mi);t[v].ma=max(t[v*2].ma,t[v*2+1].ma);t[v].l=t1[v].l=0;
t1[v].mi&