【NOIP2016提高A组模拟8.14】火神的鱼

来源:互联网 发布:网络交换机有辐射吗 编辑:程序博客网 时间:2024/05/01 00:33

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 longusing 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=max(t1[v*2].mi,t1[v*2+1].mi);t1[v].ma=max(t1[v*2].ma,t1[v*2+1].ma);}void down(int v){    ll l=t[v].l;if(l==0) return;    t[v*2].mi+=l;t[v*2+1].mi+=l;t[v*2].ma+=l;t[v*2+1].ma+=l;t[v*2].l+=l;t[v*2+1].l+=l;t[v].l=0;}void down1(int v){    ll l=t1[v].l;if(l==0) return;    t1[v*2].mi+=l;t1[v*2+1].mi+=l;t1[v*2].ma+=l;t1[v*2+1].ma+=l;t1[v*2].l+=l;t1[v*2+1].l+=l;t1[v].l=0;}void changx(int v,int i,int j,int x,int y,ll z){    if(i==x&&j==y){t[v].l+=z;t[v].mi+=z;t[v].ma+=z;return;}    int m=(i+j)/2;down(v);    if(y<=m) changx(v*2,i,m,x,y,z);    else if(x>m) changx(v*2+1,m+1,j,x,y,z);         else changx(v*2,i,m,x,m,z),changx(v*2+1,m+1,j,m+1,y,z);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);}void changy(int v,int i,int j,int x,int y,ll z){    if(i==x&&j==y){t1[v].l+=z;t1[v].mi+=z;t1[v].ma+=z;return;}    int m=(i+j)/2;down1(v);    if(y<=m) changy(v*2,i,m,x,y,z);    else if(x>m) changy(v*2+1,m+1,j,x,y,z);         else changy(v*2,i,m,x,m,z),changy(v*2+1,m+1,j,m+1,y,z);ans[v]=ans[v*2]+ans[v*2+1];    t1[v].mi=max(t1[v*2].mi,t1[v*2+1].mi);t1[v].ma=max(t1[v*2].ma,t1[v*2+1].ma);}void find1(int v,int i,int j){    if(i==j){if(t1[v].ma>=y1&&t1[v].ma<=y2) ans[v]=1;else ans[v]=0;t[v].ma=t[v].mi;t[v].mi=INF;return;}    int m=(i+j)/2;down(v);down1(v);    if(t[v*2].mi>=x1) find1(v*2,i,m);else find1(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);    t1[v].mi=max(t1[v*2].mi,t1[v*2+1].mi);t1[v].ma=max(t1[v*2].ma,t1[v*2+1].ma);}void find2(int v,int i,int j){    if(i==j){ans[v]=0;t1[v].mi=t1[v].ma=t[v].mi=t[v].ma=INF;return;}    int m=(i+j)/2;down(v);down1(v);    if(t[v*2].ma>x2) find2(v*2,i,m);else find2(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);    t1[v].mi=max(t1[v*2].mi,t1[v*2+1].mi);t1[v].ma=max(t1[v*2].ma,t1[v*2+1].ma);}void find3(int v,int i,int j){    if(i==j){if(t[v].ma>=x1&&t[v].ma<=x2) ans[v]=1;else ans[v]=0;t1[v].ma=t1[v].mi;t1[v].mi=INF;return;}    int m=(i+j)/2;down1(v);down(v);    if(t1[v*2].mi>=y1) find3(v*2,i,m);else find3(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);    t1[v].mi=max(t1[v*2].mi,t1[v*2+1].mi);t1[v].ma=max(t1[v*2].ma,t1[v*2+1].ma);}void find4(int v,int i,int j){    if(i==j){ans[v]=0;t1[v].mi=t1[v].ma=t[v].mi=t[v].ma=INF;return;}    int m=(i+j)/2;down1(v);down(v);    if(t1[v*2].ma>y2) find4(v*2,i,m);else find4(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);    t1[v].mi=max(t1[v*2].mi,t1[v*2+1].mi);t1[v].ma=max(t1[v*2].ma,t1[v*2+1].ma);}void get(int v,int i,int j,int x,int y){    if(i==x&&j==y) {an+=ans[v];return;}    int m=(i+j)/2;    if(y<=m) get(v*2,i,m,x,y);    else if(x>m) get(v*2+1,m+1,j,x,y);         else get(v*2,i,m,x,m),get(v*2+1,m+1,j,m+1,y);}int main(){    for(scanf("%d",&ac);ac;ac--)    {        scanf("%d",&n);scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);        fo(i,1,n)        {            ll x,y;scanf("%lld%lld",&x,&y);            a[i][1]=x;a[i][2]=y;        }        memset(t,0,sizeof(t));memset(t1,0,sizeof(t1));build(1,1,n);int m;        for(scanf("%d",&m);m;m--)        {            int ta;scanf("%d",&ta);            if(ta==1)            {                int x,y;ll z;scanf("%d%d%lld",&x,&y,&z);                changx(1,1,n,x,y,z);                while(t[1].mi>=x1) find1(1,1,n);                while(t[1].ma>x2) find2(1,1,n);            }            if(ta==2)            {                int x,y;ll z;scanf("%d%d%lld",&x,&y,&z);                changy(1,1,n,x,y,z);                while(t1[1].mi>=y1) find3(1,1,n);                while(t1[1].ma>y2) find4(1,1,n);            }            if(ta==3)            {                int x,y;scanf("%d%d",&x,&y);                an=0;get(1,1,n,x,y);printf("%lld\n",an);            }        }    }}
1 0