把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P5816 [CQOI2010]内部白点

题面传送门
首先有一个结论就是不存在二次变换。
如果存在二次变换,那么二次变换那个点的至少一个方向会新出现一个点,但是要新出现一个点那个方向必定原来就存在一个点。所以不成立。
那么就可以从上到下做扫描线,当碰到一列最上面的点时给树状数组那个位置加一,最下面减一就好了。
代码实现:

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
int n,m,k,longge,now,last,f[200039],x[100039],y[100039],z,nows[200039],tots[200039],l,r,mid,s1[200039],s2[200039],minn[200039],maxn[200039];
long long ans;
vector<int> s[200039];
inline int ls(int x){
	l=0;r=2*n+1;
	while(l+1<r){
		mid=(l+r)>>1;
		if(nows[mid]<x) l=mid;
		else r=mid;
	}
	return  tots[r];
}
inline void get(int x,int y){while(x<=2*n) f[x]+=y,x+=x&-x;}
inline int find(int x){int ans=0;while(x) ans+=f[x],x-=x&-x;return ans;}
int main(){
//	freopen("1.in","r",stdin);
	register int i,j;
	scanf("%d",&n);
	for(i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]),nows[i*2-1]=x[i],nows[i*2]=y[i];
	sort(nows+1,nows+2*n+1);
	nows[0]=nows[1]-1;
	for(i=1;i<=2*n;i++){
		tots[i]=tots[i-1];
		if(nows[i]!=nows[i-1]) tots[i]++;
	}
	memset(minn,0x3f,sizeof(minn));
	memset(s1,0x3f,sizeof(s1));
	for(i=1;i<=n;i++)x[i]=ls(x[i]),y[i]=ls(y[i]);
	for(i=1;i<=n;i++) s[x[i]].push_back(y[i]);
	for(i=1;i<=n;i++) maxn[x[i]]=max(maxn[x[i]],y[i]),minn[x[i]]=min(minn[x[i]],y[i]);
	for(i=1;i<=n;i++) s1[y[i]]=min(s1[y[i]],x[i]),s2[y[i]]=max(s2[y[i]],x[i]);
	for(i=1;i<=2*n;i++){
		longge=s[i].size();
		for(j=0;j<longge;j++) {
			last=s[i][j];
			if(s1[last]==i) get(last,1);
			if(s2[last]==i) get(last,-1);
		}
		if(longge<2) continue;
		for(j=0;j<longge;j++){
			last=s[i][j];
			if(i!=s2[last]) ans--;
		}
		ans+=find(maxn[i])-find(minn[i]-1);  
		//printf("%d\n",ans);
	}
	printf("%lld\n",ans+n);
}
posted @ 2020-10-07 21:56  275307894a  阅读(43)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end