欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

HDU6681 二维偏序计算贡献值 树状数组 离散化

程序员文章站 2024-03-20 09:42:04
...

http://acm.hdu.edu.cn/showproblem.php?pid=6681

交点个数加1就是答案

使用二维偏序计算横竖射线的交点

#include <bits/stdc++.h>
using namespace std;
int T,n,m,k;
struct point {
    int x,y;
    int kind;
    point(int a,int b,int k = 0):x(a),y(b),kind(k) {};
};

vector<point>p[5];

void input() {
    int a,b;
    char s[2];
    scanf("%d%d%s",&a,&b,s);
    point pp(a,b);
    switch(s[0]) {
    case 'U':
        pp.kind = 1;
        p[1].push_back(pp);
        break;
    case 'D':
        pp.kind = 2;
        p[2].push_back(pp);
        break;
    case 'L':
        pp.kind = 3;
        p[3].push_back(pp);
        break;
    case 'R':
        pp.kind = 4;
        p[4].push_back(pp);
        break;
    }
}
void init(){
    for(int i = 1;i<=4;i++){
        p[i].clear();
    }
}
bool cmpx(point a,point b){
    return a.x<b.x;
}
bool cmpy(point a,point b){
    return a.y<b.y;
}
int c[100005] = {0};
void cinit(){
    memset(c,0,sizeof(c));
}
int ask(int x){
    int ans = 0;
    for(;x;x-=x&-x)ans+=c[x];
    return ans;
}
void add(int x,int y){
    for(;x<=100000;x+=x&-x)c[x]+=y;
}
int solve(int a,int b,bool changex,bool changey){
    ///计算每一个b类点的左下方向有几个a类点,返回对每一个b类点计算的和
    ///changex、y表示是否翻转x、y坐标
    ///比如实际计算的是左上方的点,只要翻转y轴就可以转换成计算左下方的点
    ///把a类点和b类点放在一起排序,扫描到a类点时,对树状数组做单点修改,
    ///扫描到b类点时将树状数组的前缀和加到返回值上
    vector<point> v;
    v.insert(v.end(),p[a].begin(),p[a].end());
    v.insert(v.end(),p[b].begin(),p[b].end());
    if(changex){
        for(int i = 0;i<(int)v.size();i++){
            v[i].x = 1e9 - v[i].x;
        }
    }
    if(changey){
        for(int i = 0;i<(int)v.size();i++){
            v[i].y = 1e9 - v[i].y;
        }
    }
    sort(v.begin(),v.end(),cmpy);
    for(int i = 0;i<(int)v.size();i++){
        v[i].y = i+1;///树状数组存储的是y轴坐标,因为y轴坐标范围很大,所以要先离散化
    }
    sort(v.begin(),v.end(),cmpx);
    cinit();
    int ret = 0;
    for(int i = 0;i<(int)v.size();i++){
        if(v[i].kind == a){
            add(v[i].y,1);
        }else{
            ret+=ask(v[i].y);
        }
    }
    return ret;
}

int main() {
    scanf("%d",&T);
    while(T--) {
        init();
        scanf("%d%d%d",&n,&m,&k);
        for(int i = 1; i<=k; i++) {
            input();
        }
        int ans = 0;
        ans += solve(1,3,0,0);
        ans += solve(1,4,1,0);
        ans += solve(2,3,0,1);
        ans += solve(4,2,0,0);
        printf("%d\n",ans+1);
    }
    return 0;
}