zoukankan      html  css  js  c++  java
  • 暴力枚举+扫描线+线段树——cf1194E

    /*
    思路就是枚举矩形下面那条先,把所有和其交叉的竖线更新进线段树,然后扫描先向上更新,遇到竖线上端点就在线段树里删掉,遇到横线就更新答案
    */
    #include<bits/stdc++.h> using namespace std; #define N 20005 #define ll long long struct SegV{int x,y1,y2;}v[N];//垂直线 struct SegH{int y,x1,x2;}h[N];//水平线 int cmp(SegH a,SegH b){return a.y<b.y;} int n,cntv,cnth; int y[N],cnty,x[N],cntx; vector<SegV>Up[N],Down[N]; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int sum[N<<2]; void update(int pos,int v,int l,int r,int rt){ if(l==r){sum[rt]+=v;return;} int m=l+r>>1; if(pos<=m)update(pos,v,lson); else update(pos,v,rson); sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } int query(int L,int R,int l,int r,int rt){ if(L<=l && R>=r)return sum[rt]; int m=l+r>>1,res=0; if(L<=m)res+=query(L,R,lson); if(R>m)res+=query(L,R,rson); return res; } int main(){ cin>>n; for(int i=1;i<=n;i++){ int x1,x2,y1,y2; cin>>x1>>y1>>x2>>y2; x[++cntx]=x1;x[++cntx]=x2; y[++cnty]=y1;y[++cnty]=y2; if(x1==x2){//垂直线 cntv++; v[cntv].x=x1; v[cntv].y1=min(y1,y2); v[cntv].y2=max(y1,y2); } else { cnth++; h[cnth].y=y1; h[cnth].x1=min(x1,x2); h[cnth].x2=max(x1,x2); } } sort(x+1,x+1+cntx); cntx=unique(x+1,x+1+cntx)-x-1; sort(y+1,y+1+cnty); cnty=unique(y+1,y+1+cnty)-y-1; for(int i=1;i<=cnth;i++){ h[i].y=lower_bound(y+1,y+1+cnty,h[i].y)-y; h[i].x1=lower_bound(x+1,x+1+cntx,h[i].x1)-x; h[i].x2=lower_bound(x+1,x+1+cntx,h[i].x2)-x; } for(int i=1;i<=cntv;i++){ v[i].x=lower_bound(x+1,x+1+cntx,v[i].x)-x; v[i].y1=lower_bound(y+1,y+1+cnty,v[i].y1)-y; v[i].y2=lower_bound(y+1,y+1+cnty,v[i].y2)-y; } sort(h+1,h+1+cnth,cmp);//给水平线从低到高排序 for(int i=1;i<=cntv;i++){//按端点处理垂直线 Up[v[i].y2].push_back(v[i]); Down[v[i].y1].push_back(v[i]); } long long ans=0; for(int i=1;i<=cnth;i++){ memset(sum,0,sizeof sum); //把所有和h[i]交叉的竖线更新进线段树 for(int j=1;j<=cntv;j++) if(v[j].y1<=h[i].y && v[j].y2>=h[i].y) update(v[j].x,1,1,cntx,1); //开始向上枚举所有水平线 int now=h[i].y;//当前的高度 for(int j=i+1;j<=cnth;j++)if(h[i].y!=h[j].y){ while(now+1<=h[j].y){ ++now; for(auto v:Up[now-1]){//把这个高度以下的都删掉 if(v.y1<=h[i].y) update(v.x,-1,1,cntx,1); } } int L=max(h[i].x1,h[j].x1),R=min(h[i].x2,h[j].x2); if(L<=R){ int res=query(L,R,1,cntx,1); ans+=res*(res-1)/2; } } } cout<<ans<<endl; }
  • 相关阅读:
    ubuntu开机挂载磁盘盘出现:Metadata kept in Windows cache, unable to mount
    ubuntuaptgetoldversion
    evince 41.2ubuntu 16.04snap
    ubuntu坚果云安装deb后启动不了
    电影票分析
    jieba分词讲解2
    期末总结建议
    软件架构师工作看法
    jieba分词讲解1
    1
  • 原文地址:https://www.cnblogs.com/zsben991126/p/11630677.html
Copyright © 2011-2022 走看看