codeforces 1190D-Tokitsukaze and Strange Rectangle

Keywords: PHP

Portal: QAQQAQ

 

Topic: Give you N points on the coordinate axis. Ask you the number of different point sets divided by one horizontal line and two vertical lines (excluding empty sets).

 

Thought: When I don't think clearly, I think it's a water problem: for y-axis sort, then scan from bottom to top to see the number of X different s, ans+=(s+1)*s/2 above, but later I found that this will be repeated to consider some sets, that is, at the current point, these points are sequential about x-axis sort, after deleting this point is still continuous, so we need to subtract these points from y-axis scan. Repeated sets

 

That is to say, for Y-axis sorting, we scan from top to bottom. For the newly added layer y, we first add (s+1)*s/2, and then find out how many x exists in the gap between them for each x value, minus the repeated set tmp*(tmp+1)/2.

In terms of code implementation, we use line segment tree to maintain x-value L and how many points exist in R interval. When a layer is swept away, we update the original non-existent x-value to 1. If x exists, we don't care about it. We should note that sum maintains the number of different x-axes, not the total number of points.

In updating the answer, for query between two X at the same level, subtract tmp*(tmp+1)/2 from the original number of different x values, and pay attention to sweep both the beginning and the end, and the line segment tree opens to xn+1 in order to prevent crossing the boundary.

Because x, y <= 1e9 can't maintain such a large section directly with the segment tree, and N <= 2e5, we can use common techniques to discretize it.

 

Code: (I heard that tree array maintenance is more convenient, but I like segment tree ah...)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=200005;
const ll inf=2000000000;
 
struct node{
    ll x,y;
    bool operator < (const node rhs) const{
        if(y==rhs.y) return x<rhs.x;
        return y>rhs.y;
    }
}a[N];
 
ll n,x[N],y[N],mx=-inf,vis[N];
 
struct TREE{
    ll sum;
}tree[N*4];
 
void push_up(TREE &fa,TREE ls,TREE rs)
{
    fa.sum=ls.sum+rs.sum;
}
 
void build(ll x,ll l,ll r)
{
    if(l==r) 
    {
        tree[x].sum=0;
        return;
    }
    ll mid=(l+r)>>1;
    build(x+x,l,mid);
    build(x+x+1,mid+1,r);
    push_up(tree[x],tree[x+x],tree[x+x+1]);
}
 
void update(ll x,ll l,ll r,ll pos)
{
    if(l==r)
    {
        tree[x].sum=1;
        return;
    }
    ll mid=(l+r)>>1;
    if(pos>mid) update(x+x+1,mid+1,r,pos);
    if(pos<=mid) update(x+x,l,mid,pos);
    push_up(tree[x],tree[x+x],tree[x+x+1]);
}
 
ll query(ll x,ll l,ll r,ll L,ll R)
{
    if(L>R) return 0;
    if(L<=l&&r<=R) return tree[x].sum;
    ll mid=(l+r)>>1;
    if(mid>=R) return query(x+x,l,mid,L,R);
    if(mid<L) return query(x+x+1,mid+1,r,L,R);
    return query(x+x,l,mid,L,R)+query(x+x+1,mid+1,r,L,R);
}
 
int main()
{
    scanf("%lld",&n);
    for(ll i=1;i<=n;i++) 
    {
        scanf("%lld%lld",&a[i].x,&a[i].y);
        x[i]=a[i].x; y[i]=a[i].y;
    }
    sort(x+1,x+n+1); sort(y+1,y+n+1);
    ll xn=unique(x+1,x+n+1)-x-1;
    ll yn=unique(y+1,y+n+1)-y-1;
    for(ll i=1;i<=n;i++)
    {
        a[i].x=lower_bound(x+1,x+xn+1,a[i].x)-x;
        a[i].y=lower_bound(y+1,y+yn+1,a[i].y)-y;
    }
    sort(a+1,a+n+1);
    build(1,1,xn+1);
    ll ans=0,sum=0;
    ll beg=1,now=1;
    memset(vis,0,sizeof(vis));
    while(beg<=n)
    {
        ll pre=0;
        while(a[beg].y==a[now].y&&now<=n)
        {
            ll tmp=query(1,1,xn+1,pre+1,a[now].x-1);
            ans-=tmp*(tmp+1)/2;
            pre=a[now].x;
            now++;
        }
        ll tmp=query(1,1,xn+1,pre+1,xn);
        ans-=tmp*(tmp+1)/2;
        while(beg<now)
        {
            if(!vis[a[beg].x])
            {
                sum++;
                vis[a[beg].x]=1;
                update(1,1,xn+1,a[beg].x);
            }
            beg++;
        }
        ans+=(sum+1)*sum/2;
    }
    cout<<ans<<endl;
    return 0;
}

Posted by gleemonex on Mon, 14 Oct 2019 07:56:19 -0700