1. 程式人生 > >POJ 3416 Crossing

POJ 3416 Crossing

題意 break oss using con stream 當前 names ems

題目:http://poj.org/problem?id=3416

題意:給你一些點,之後再給你一些點來建立坐標系,問你一三象限的點個數和二四象限的點個數的差

這個題目我們應該離線處理,考慮建立2個樹狀數組,一個維護當前坐標系的右邊點數目,一個維護左邊

首先對點和查詢的點進行以x從小到大排序,開始將所有點放入右邊

之後開始枚舉要查詢的點,將在該點左邊的數從右邊刪除並加入左邊,然後分別求和算結果

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
const int N=5e5+5;
struct p
{
    int x,y,id;
    bool operator <(const p&t) const
    {
        return x<t.x;
    }
};
p a[N],b[N];
int n,m;
int l[N],r[N],ans[N];
void add(int *s,int i,int x)
{
    while(i<=500001)
    {
        s[i]+=x;
        i+=i&-i;
    }
}
int sum(int *s,int i)
{
    int tem=0;
    while(i>0)
    {
        tem+=s[i];
        i-=i&-i;
    }
    return tem;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&a[i].x,&a[i].y);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&b[i].x,&b[i].y);
            b[i].id=i;
        }
        sort(a+1,a+1+n);
        sort(b+1,b+1+m);
        memset(l,0,sizeof(l));
        memset(r,0,sizeof(r));
        for(int i=1;i<=n;i++)
            add(r,a[i].y+1,1);
        int st=1,ed;
        for(int i=1;i<=m;i++)
        {
            for(ed=st;ed<=n;ed++)
                if (a[ed].x>b[i].x)
                    break;
            for(int j=st;j<ed;j++)
            {
                add(r,a[j].y+1,-1);
                add(l,a[j].y+1,1);
            }
            int t=sum(r,500001)-sum(r,b[i].y+1)+sum(l,b[i].y+1);
            int tt=sum(l,500001)-sum(l,b[i].y+1)+sum(r,b[i].y+1);
            ans[b[i].id]=abs(t-tt);
            st=ed;
        }
        for(int i=1;i<=m;i++)
            printf("%d\n",ans[i]);
        if (T) printf("\n");
    }
    return 0;
}

  

POJ 3416 Crossing