n方做法只跑了22ms
查看原帖
n方做法只跑了22ms
404407
OUYE2020楼主2021/8/24 21:50

本来想写线段树的,感觉太麻烦,于是写了 map\rm map 存下区间然后暴力扫的 O(n2)O(n^2) 扫描线的做法。本想着再卡卡常,结果跑这么快。

后来想了想,这个最坏 O(n2)O(n^2) 的做法如果不有意卡的话,可以跑到的期望是 O(nn)O(n\sqrt{n}) 对吧。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#define ll long long
#define uns unsigned
#define MAXN 5005
#define INF 1e17
#define lowbit(x) ((x)&(-(x)))
#define IF it->first
#define IS it->second
using namespace std;
inline ll read(){
	ll x=0;bool f=1;char s=getchar();
	while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}
	while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+s-'0',s=getchar();
	return f?x:-x;
}
int n,Q,m;
struct itn{
	int l,r;itn(){}
	itn(int L,int R){l=L,r=R;}
	bool operator<(const itn&b)const{
		if(l!=b.l)return l<b.l;
		else return r<b.r;
	}
};
pair<int,itn>pr,e[MAXN<<1];
map<itn,int>mp;
map<itn,int>::iterator it;
signed main()
{
	n=read(),m=0;
	for(int i=1;i<=n;i++){
		int x=read(),y=read(),x_=read(),y_=read();
		pr.first=y,pr.second=itn(x,x_),e[++m]=pr;
		pr.first=y_,pr.second=itn(x_,x),e[++m]=pr;
	}
	sort(e+1,e+1+m);
	mp.clear();
	ll s=0,bf=-20000,ans=0;
	for(int i=1;i<=m;i++){
		int y=e[i].first,l=e[i].second.l,r=e[i].second.r;
		int iv=1;
		if(l>r)swap(l,r),iv=-1;
		ans+=s*(y-bf),bf=y;
		if(iv<0){
			mp[itn(l,r)]+=iv;
			if(mp[itn(l,r)]==0)mp.erase(itn(l,r));
		}
		int lt=-20000,rt=-20000,len=r-l;
		for(it=mp.begin();it!=mp.end();it++){
			if(IF.l<=rt)rt=max(rt,IF.r);
			else len-=max(min(r,rt)-max(l,lt),0),lt=IF.l,rt=IF.r;
		}
		len-=max(min(r,rt)-max(l,lt),0),ans+=len;
		if(iv>0)mp[itn(l,r)]+=iv;
		lt=-20000,rt=-20000;s=0;
		for(it=mp.begin();it!=mp.end();it++){
			if(IF.l<=rt)rt=max(rt,IF.r);
			else s+=2,lt=IF.l,rt=IF.r;
		}
	}
	printf("%lld\n",ans);
	return 0;
}
2021/8/24 21:50
加载中...