Bridge next to the APIO2015 eight neighborhood / neighborhood bar next to the bridge

Subject description:

bz

luogu

answer:

Greedy + weights tree line.

$ K = 1 $, when the answer is $ \ sum | xl | + | xr | $, so the median after all endpoints can be sorted taken.

$ K = 2 $, they must take the left are some of the bridge on the left, to the right of some to go to the right of the bridge.

The question is what sort order.

The answer is sorted by the midpoint of the segment.

The reason is that, for a pair of points on both sides of the river and two bridges, selection must be near the midpoint of the offline segment.

Consider how quickly calculate the answer, we can use weights segment tree maintenance intervals and the median. (Of course, also be used a balanced tree)

Code:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 100050;
const int M = 100*N;
template<typename T>
inline void read(T&x)
{
    T f = 1,c = 0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
    x = f*c;
}
int K,n;
ll ans;
char op1[2],op2[2];
struct Point
{
    you have to, to;
    Point(){}
    Point(int l,int r):l(l),r(r){}
    bool operator < (const Point&a)const{return l+r<a.l+a.r;}
}p[N];
int s[N<<1],tl;
const int inf = 2000000001;
struct segtree
{
    int rt,tot,ls[M],rs[M],siz[M];
    ll sum[M];
    void insert(int l,int r,int&u,int qx)
    {
        if(!u)u=++tot;siz[u]++,sum[u]+=qx;
        if(l==r)return ;
        int mid = (l+r)>>1;
        if(qx<=mid)insert(l,mid,ls[u],qx);
        else insert(mid+1,r,rs[u],qx);
    }
    void erases ( you have to, you're down, you and, you QX)
    {
        siz[u]--,sum[u]-=qx;if(l==r)return ;
        int mid = (l+r)>>1;
        if(qx<=mid)erase(l,mid,ls[u],qx);
        else erase(mid+1,r,rs[u],qx);
    }
    you query ( you have to, you're down, you and, you rk)
    {
        if(!u)return -1;
        if(l==r)return l;
        int mid = (l+r)>>1;
        if(rk<=siz[ls[u]])return query(l,mid,ls[u],rk);
        else return query(mid+1,r,rs[u],rk-siz[ls[u]]);
    }
    ll query ( you have to, you're down, you and, you QL, you qr)
    {
        if(!u||ql>qr)return 0;
        if(l==ql&&r==qr)return sum[u];
        int mid = (l+r)>>1;
        if(qr<=mid)return query(l,mid,ls[u],ql,qr);
        else if(ql>mid)return query(mid+1,r,rs[u],ql,qr);
        else return query(l,mid,ls[u],ql,mid)+query(mid+1,r,rs[u],mid+1,qr);
    }
    ll Query ( you have to, you're down, you and, you QL, you qr)
    {
        if(!u||ql>qr)return 0;
        if(l==ql&&r==qr)return siz[u];
        int mid = (l+r)>>1;
        if(qr<=mid)return Query(l,mid,ls[u],ql,qr);
        else if(ql>mid)return Query(mid+1,r,rs[u],ql,qr);
        else return Query(l,mid,ls[u],ql,mid)+Query(mid+1,r,rs[u],mid+1,qr);
    }
    ll query(int siz)
    {
        int mid = query(0,inf,rt,siz);
        ll ql = query(0,inf,rt,0,mid-1),qr = query(0,inf,rt,mid+1,inf),tmp = (Query(0,inf,rt,mid+1,inf)-Query(0,inf,rt,0,mid-1));
        return qr-ql-tmp*mid;
    }
} tr [ 2 ];
int main ()
{
//    freopen("tt.in","r",stdin);
    read(K),read(n);
    for(int x,y,i=1;i<=n;i++)
    {
        scanf("%s",op1),read(x),scanf("%s",op2),read(y);
        if(x>y)swap(x,y);
        if(op1[0]==op2[0])
        {
            years + y = x;
            i--,n--;
        }else p[i]=Point(x,y);
    }
    ans+=n;
    if(!n)
    {
        printf("%lld\n",ans);
        return 0;
    }
    if(K==1)
    {
        for(int i=1;i<=n;i++)
            s[++tl]=p[i].l,s[++tl]=p[i].r;
        sort(s+1,s+tl+1);
        int mid = (s[tl/2]+s[tl/2+1])/2;
        int i;
        for(i=1;s[i]<=mid;i++)ans+=mid-s[i];
        for(;i<=tl;i++)ans+=s[i]-mid;
        printf("%lld\n",ans);
        return 0;
    }
    sort(p+1,p+1+n);
    for(int i=1;i<=n;i++)
        tr[1].insert(0,inf,tr[1].rt,p[i].l),tr[1].insert(0,inf,tr[1].rt,p[i].r);
    ll mx = 0x3f3f3f3f3f3f3f3fll;
    for(int i=1;i<=n;i++)
    {
        tr[0].insert(0,inf,tr[0].rt,p[i].l),tr[0].insert(0,inf,tr[0].rt,p[i].r);
        tr[1].erase (0,inf,tr[1].rt,p[i].l),tr[1].erase (0,inf,tr[1].rt,p[i].r);
        mx=min(mx,tr[0].query(i)+tr[1].query(n-i));
    }
    printf("%lld\n",ans+mx);
    return 0;
}
View Code

 

Guess you like

Origin www.cnblogs.com/LiGuanlin1124/p/11094530.html