【题解】【老C的任务】

题目内容

Solution

对于每个询问可以拆分成4个前缀矩形的求和,容易发现,前缀矩形的求和相当于是求一个二维偏序,可以用树状数组或cdq分治在nlogn的复杂度内完成。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
	register int x=0,w=1;
	register char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if(ch=='-') {ch=getchar();w=-1;}
	while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return x*w;
}
inline void write(int x)
{
	if(x<0) {putchar('-');x=~(x-1);}
	if(x>9) write(x/10);
	putchar('0'+x%10);
}//Make sure that the left won't make a difference to the right
//If it is true,there is no need to unique 
const int N=1e5+100;
int n,m,ans[N];
struct node{
	int x,y,z,p,sum,id,tag;
	bool operator<(const node& g)const
	{
		if(x^g.x) return x<g.x;
		if(y^g.y) return y<g.y;
		return z<g.z;
	}
}a[N*5],tmp[N*5];
int cnt;
void cdq(int l,int r)
{
	if(l==r) return;
	int mid=l+r>>1;
	cdq(l,mid);
	cdq(mid+1,r);
	int sum=0,pos=l;
	for(int i=mid+1;i<=r;++i)
	{
		while(pos<=mid&&a[pos].y<=a[i].y) sum+=a[pos].p,pos++;
		a[i].sum+=sum;
	}
	int p=l,q=mid+1;
	for(int i=l;i<=r;++i)
	  if(p>mid) tmp[i]=a[q++];
	  else if(q>r) tmp[i]=a[p++];
	  else tmp[i]=a[a[p].y<a[q].y?p++:q++];
	for(int i=l;i<=r;++i) a[i]=tmp[i];
}
signed main()
{
    n=read();m=read();
    for(int i=1;i<=n;++i)
    {
    	int x=read(),y=read(),p=read();
    	a[i]={x,y,0,p};
	}
	cnt=n;
	for(int i=1;i<=m;++i)
	{
		int x[3],y[3];
		x[1]=read(),y[1]=read();
		x[2]=read(),y[2]=read();
		a[++cnt]={x[2],y[2],1,0,0,i,1};
		a[++cnt]={x[2],y[1]-1,1,0,0,i,-1};
		a[++cnt]={x[1]-1,y[2],1,0,0,i,-1};
		a[++cnt]={x[1]-1,y[1]-1,1,0,0,i,1};
	}
	sort(a+1,a+cnt+1);
	cdq(1,cnt);
	for(int i=1;i<=cnt;++i)
	if(a[i].z)
	ans[a[i].id]+=a[i].sum*a[i].tag;
	for(int i=1;i<=m;++i)
	{
		write(ans[i]);puts("");
	}
	return 0;
}
上一篇:算法: 验证回文680. Valid Palindrome II


下一篇:堆排序