E

题:https://codeforces.com/contest/1401/problem/E

题意:给定n条横线,m条竖线,问(0,0)到(1e6,1e6)的正方形被分割成几部分,强条件:每个线段与正方形的至少一条边相交,并且没有线段共线。

分析:平行于x轴的线段记左端点贡献为1,右端点+1位置贡献为-1;

   以平行于y轴做一条扫描线(从x=0扫到x=1e6),若扫到平行于x轴的线段,则将贡献点加到以y轴为单位的树状数组上,然后统计当前位置存在的平行于y轴的线段产生的贡献。

#include<bits/stdc++.h>
using namespace std;
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define MP make_pair
typedef long long ll;
const ll INF=1e18;
const int inf=0x3f3f3f3f;
const int M=1e6+6;
ll tr[M];
vector<pii >a[M],b[M];
void add(int x,int c){
    while(x<=1e6){
        tr[x]+=c;
        x+=x&(-x);
    }
}
ll sum(int x){
    ll res=0;
    while(x){
        res+=tr[x];
        x-=x&(-x);
    }
    return res;
}
int main(){
    int n,m;
    ll ans=1;
    scanf("%d%d",&n,&m);
    for(int y,x1,x2,i=1;i<=n;i++){
        scanf("%d%d%d",&y,&x1,&x2);
        a[x1].pb(MP(y,1));
        a[x2+1].pb(MP(y,-1));
        if(x1==0&&x2==1e6)
            ans++;
    }
    for(int x,y1,y2,i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y1,&y2);
        b[x].pb(MP(y1,y2));
        if(y1==0&&y2==1e6)
            ans++;
    }
    for(int i=0;i<=1e6;i++){
        for(auto it:a[i])
            add(it.first,it.second);
        for(auto it:b[i]){
            ll tmp1=sum(it.second);
            int l=it.first;
            ll tmp2;
            if(l==0)
                tmp2=0;
            else
                tmp2=sum(l-1);
            ans+=tmp1-tmp2;
        }
    }
    printf("%lld
",ans);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/starve/p/13544267.html