记录编号 344597 评测结果 AAAAAAAAAA
题目名称 [HZOI 2016] 小鱼之美 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 32.430 s
提交时间 2016-11-10 13:08:22 内存使用 38.03 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=500010;
int t,n,m,X[2][2],x[N][2];
#define lc x<<1
#define rc (x<<1)|1
long long tag[N][2];int now;
void change(int x,int l,int r,int L,int R,int d1,int d2){
	if (l>=L&&r<=R){tag[x][0]+=d1;tag[x][1]+=d2;return;}
	int mid=(l+r)>>1;
	if (R>mid) change(rc,mid+1,r,L,R,d1,d2);
	if (L<=mid) change(lc,l,mid,L,R,d1,d2);
}
int visit(int x,int l,int r,int p){
	while (l!=r){
		tag[lc][0]+=tag[x][0];
		tag[lc][1]+=tag[x][1];
		tag[rc][0]+=tag[x][0];
		tag[rc][1]+=tag[x][1];
		tag[x][0]=tag[x][1]=0;
		int mid=(l+r)>>1;
		if (p>mid) l=mid+1,x=rc;
			else r=mid,x=lc;
	}
	return x;
}
struct ask{int tp,l,r,x,y;}q[N];
void go_to(int T){//将时间戳转移到T时刻 
	while (now<T){
		now++;
		if (q[now].tp!=3) change(1,1,n,q[now].l,q[now].r,q[now].x,q[now].y);
	}
	while (now>T){
		if (q[now].tp!=3) change(1,1,n,q[now].l,q[now].r,-q[now].x,-q[now].y);
		now--;
	}
}
int ansl[N],ansr[N],a[N],b[N];
//鱼i时间在[ansl[i],ansr[i]]内处于网内 
//整体二分,得到鱼在网内的最小时刻和最大时刻 
//[l,r]为答案区间,[L,R]为询问区间 
void solvel(int l,int r,int L,int R){
	if (L>R) return;
	if (l==r){
		for (int i=L;i<=R;i++) ansl[a[i]]=l;
		return;
	}
	int mid=(l+r)>>1,lp=L-1,rp=R+1;
	go_to(mid);
	for (int i=L;i<=R;i++){
		int v=a[i],p=visit(1,1,n,v);
		if (x[v][0]+tag[p][0]>=X[0][0]&&x[v][1]+tag[p][1]>=X[0][1])
			b[++lp]=v;else b[--rp]=v;
	}
	for (int i=L;i<=R;i++) a[i]=b[i];
	solvel(l,mid,L,lp);
	solvel(mid+1,r,rp,R);
}
void solver(int l,int r,int L,int R){
	if (L>R) return;
	if (l==r){
		for (int i=L;i<=R;i++) ansr[a[i]]=l;
		return;
	}
	int mid=(l+r)>>1,lp=L-1,rp=R+1;
	go_to(mid+1);
	for (int i=L;i<=R;i++){
		int v=a[i],p=visit(1,1,n,v);
		if (x[v][0]+tag[p][0]<=X[1][0]&&x[v][1]+tag[p][1]<=X[1][1])
			b[--rp]=v;else b[++lp]=v;
	}
	for (int i=L;i<=R;i++) a[i]=b[i];
	solver(l,mid,L,lp);
	solver(mid+1,r,rp,R);
}
struct bit{
	int a[N];
	int sum(int r){
		int ans=0;
		for (;r;r-=(r&-r)) ans+=a[r];
		return ans;
	}
	int sum(int l,int r){return sum(r)-sum(l-1);}
	void add(int p,int d){
		for (;p<=n;p+=(p&-p)) a[p]+=d;
	}
	void clear(){memset(a,0,sizeof a);}
}T;
struct opt{int tp,T,l,r,p;}Q[N];
bool cmp(const opt &x,const opt &y){
	return x.T==y.T?x.tp<y.tp:x.T<y.T;
}
int ans[N];
int main()
{
	freopen("skyfishs.in","r",stdin);
	freopen("skyfishs.out","w",stdout);
	scanf("%d",&t);
	while (t--){
		scanf("%d%d%d%d%d",&n,&X[0][0],&X[0][1],&X[1][0],&X[1][1]);
		for (int i=1;i<=n;i++)
			scanf("%d%d",&x[i][0],&x[i][1]);
		scanf("%d",&m);
		T.clear();
		memset(tag,0,sizeof tag);
		memset(Q,0,sizeof Q);
		memset(q,0,sizeof q);
		for (int i=1;i<=m;i++){
			scanf("%d%d%d",&q[i].tp,&q[i].l,&q[i].r);
			if (q[i].tp==1) scanf("%d",&q[i].x);
			if (q[i].tp==2) scanf("%d",&q[i].y);
		}
		q[m+1].l=1;q[m+1].r=n;
		q[m+1].x=q[m+1].y=1e9;
		now=0;
		for (int i=1;i<=n;i++) a[i]=i;
		solvel(0,m+1,1,n);
		for (int i=1;i<=n;i++) a[i]=i;
		solver(0,m+1,1,n);
		int cnt=0;
		for (int i=1;i<=m;i++)
		if (q[i].tp==3){
			cnt++;Q[cnt].tp=3;Q[cnt].T=i;
			Q[cnt].l=q[i].l;Q[cnt].r=q[i].r;
		}
		for (int i=1;i<=n;i++)
		if (ansl[i]<=ansr[i]){
			cnt++;Q[cnt].tp=1;Q[cnt].T=ansl[i];Q[cnt].p=i;
			cnt++;Q[cnt].tp=2;Q[cnt].T=ansr[i]+1;Q[cnt].p=i;
		}
		sort(Q+1,Q+cnt+1,cmp);
		for (int i=1;i<=cnt;i++){
			if (Q[i].tp==1) T.add(Q[i].p,1);
			if (Q[i].tp==2) T.add(Q[i].p,-1);
			if (Q[i].tp==3) ans[Q[i].T]=T.sum(Q[i].l,Q[i].r);
		}
		for (int i=1;i<=m;i++)
		if (q[i].tp==3) printf("%d\n",ans[i]);
	}
	return 0;
}