• 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
    ",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;
    }
    /*
    
     */
  • 相关阅读:
    HDU 1031 Design TShirt
    普利姆(Prime)算法
    hdu 2601 An easy problem
    克鲁斯卡尔(Kruskal)算法
    双调欧几里德旅行商问题hdu 2224 The shortest path POJ 2677Tour
    求一个数个各位相加的结果时
    C语言中各种类型的范围
    获取浏览器的scrollTop有几点小疑问
    学习,学习javascript
    各种翻页的效果! FILTER: revealTrans使用说明
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/11209892.html
Copyright © 2020-2023  润新知