Codeforces 1197E Count The Rectangles(树状数组+扫描线)
题意:
给你n条平行于坐标轴的线,问你能组成多少个矩形,坐标绝对值均小于5000
保证线之间不会重合或者退化
思路:
从下到上扫描每一条纵坐标为y的水平的线,然后扫描所有竖直的线并标记与它相交的线,保证上端至少多出1
并用树状数组维护它们
然后从y+1网上扫描纵坐标为yy的水平的线,查询y到yy中同时与他们相交的竖直的线的条数算贡献即可
每查询完一个yy后,要在树状数组内删除上端点为yy的竖直的线,因为以后的yy与它不会再相交了
代码:
几乎是照着官方题解来的。。
#include<iostream> #include<cstdio> #include<algorithm> //#include<cmath> #include<cstring> #include<string> #include<stack> #include<queue> #include<deque> #include<set> #include<vector> #include<map> #define fst first #define sc second #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lc root<<1 #define rc root<<1|1 using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> PI; typedef pair<ll,ll> PLL; const db eps = 1e-6; const int mod = 1e9+7; const int maxn = 1e4+100; const int maxm = 2e6+100; const int inf = 0x3f3f3f3f; //const db pi = acos(-1.0); int n; struct node{ int l,r; int x; node(){} node(int a,int b,int c):l(a),r(b),x(c){} }; vector<node>vt[maxn],hr[maxn]; vector<int>tmp[maxn]; int tree[maxn*10]; int lowbit(int x){ return x&-x; } void add(int x,int C){ for(int i=x;i<maxn-20;i+=lowbit(i)){ tree[i]+=C; } } int sum(int x){ int ans=0; for(int i=x;i;i-=lowbit(i)){ ans+=tree[i]; } return ans; } int main(){ scanf("%d", &n); for(int i = 1; i <= n; i++){ int x1,y1,x2,y2; scanf("%d %d %d %d" ,&x1, &y1, &x2, &y2); x1+=5001;x2+=5001; y1+=5001;y2+=5001; if(x1==x2){ vt[x1].pb(node(min(y1,y2),max(y1,y2),x1)); } else{ hr[y1].pb(node(min(x1,x2),max(x1,x2),y1)); //printf("===%d\n",y1-5000); } } ll ans = 0; for(int y = 0; y < maxn-10; y++){ for(int i = 0; i < hr[y].size(); i++){ //for(int j = 0; j < maxn-10; j++)tmp[j].clear(); //mem(tree,0); node lne = hr[y][i]; int l = lne.l, r = lne.r; for(int x = l; x <= r; x++){ for(int j = 0; j < (int)vt[x].size(); j++){ if(vt[x][j].l<=y&&vt[x][j].r>=y+1){ add(x,1); tmp[vt[x][j].r].pb(x); } } } for(int yy = y+1; yy < maxn-10; yy++){ for(int j = 0; j < (int)hr[yy].size(); j++){ ll res = sum(hr[yy][j].r)-sum(hr[yy][j].l-1); ans+=res*(res-1)/2; } for(int j = 0; j < (int)tmp[yy].size(); j++){ add(tmp[yy][j],-1); } tmp[yy].clear(); } } } printf("%lld",ans); return 0; } /* */