APIO2015 八邻旁之桥

APIO2015 八邻旁之桥

题意:

​ 自己看

题解:

​ 校内模拟赛做到这题,数据范围崩了,\(K=21\)???好吧\(或K=1或2\)。切了。

​ 先判在一侧的情况。\(K=1\)桥显然在所有端点位置的中位数。\(K=2\)时,我们发现一个人总会走离\(\frac{S_i+T_i}{2}\)近的那座桥,那就按\(\frac{S_i+T_i}{2}\)排序,权值线段树在线插入&维护中位数就没了。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i,l,r) for(int i=l;i<=r;i++)
#define of(i,l,r) for(int i=l;i>=r;i--)
#define fe(i,u) for(int i=head[u];i;i=e[i].next)
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pii;
#define P(a,b) make_pair(a,b)
inline void open(const char *s)
{
    #ifndef ONLINE_JUDGE
    char str[20];
    sprintf(str,"in%s.txt",s);
    freopen(str,"r",stdin);
//  sprintf(str,"out%s.txt",s);
//  freopen(str,"w",stdout);
    #endif
}
inline ll rd()
{
    static ll x,f;
    x=0;f=1;
    char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1ll;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10ll+ch-'0';
    return f>0?x:-x;
}
const int N=100010;
const ll Inf=1e18;
int n,K,tt=0;
ll ans=0;
char s1[10],s2[10];
 
inline int fabs(int a){return a<0?-a:a;}
 
namespace K1{
ll a[N<<1];
inline void gao()
{
    int x,y;
    fo(i,1,n){
        scanf("%s",s1);x=rd();
        scanf("%s",s2);y=rd();
        if(s1[0]==s2[0]){ans+=fabs(x-y);continue;}
        a[++tt]=x;a[++tt]=y;
    }
    ans+=tt>>1;
    sort(a+1,a+tt+1);
    int pos=a[tt>>1];
    fo(i,1,tt)ans+=fabs(a[i]-pos);
    printf("%lld\n",ans);
}
 
}
 
namespace K2{
struct node{ll x,y;double val;}a[N];
ll v[N<<1],sz[2],sm[2];
int nn=0,c[N<<1],rt;
inline bool cmp(node a,node b){return a.val<b.val;}
 
namespace Seg{
#define lson tr[o].ls,l,mid
#define rson tr[o].rs,mid+1,r
#define qlson lson,L,min(mid,R)
#define qrson rson,max(mid+1,L),R
struct tree{
    int ls,rs,siz[2];ll sum[2];
    tree(){ls=rs=siz[0]=siz[1]=sum[0]=sum[1]=0;}
}tr[N<<2];int cnt=0;
 
inline void pushup(int o)
{
    tr[o].siz[0]=tr[tr[o].ls].siz[0]+tr[tr[o].rs].siz[0];
    tr[o].siz[1]=tr[tr[o].ls].siz[1]+tr[tr[o].rs].siz[1];
    tr[o].sum[0]=tr[tr[o].ls].sum[0]+tr[tr[o].rs].sum[0];
    tr[o].sum[1]=tr[tr[o].ls].sum[1]+tr[tr[o].rs].sum[1];
}
 
void build(int &o,int l,int r)
{
    o=++cnt;if(l==r){
        tr[o].siz[1]=c[l];
        tr[o].sum[1]=(ll)c[l]*v[l];
        return;
    }
    int mid=(l+r)>>1;
    build(lson);build(rson);
    pushup(o);
}
void modify(int o,int l,int r,int x)
{
    if(l==r){
        tr[o].siz[1]--;
        tr[o].sum[1]-=v[l];
        tr[o].siz[0]++;
        tr[o].sum[0]+=v[l];
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid)modify(lson,x);
    else modify(rson,x);
    pushup(o);
}
 
int querys(int o,int l,int r,int k,int t)
{
    if(l==r){
        sz[0]+=tr[o].siz[t];
        sm[0]+=tr[o].sum[t];
        return v[l];
    }
    int mid=(l+r)>>1;
    if(tr[tr[o].ls].siz[t]>=k){
        sz[1]+=tr[tr[o].rs].siz[t];
        sm[1]+=tr[tr[o].rs].sum[t];
        return querys(lson,k,t);
    }
    sz[0]+=tr[tr[o].ls].siz[t];
    sm[0]+=tr[tr[o].ls].sum[t];
    return querys(rson,k-tr[tr[o].ls].siz[t],t);
}
 
}
 
inline void gao()
{
    ll x,y;
    fo(i,1,n){
        scanf("%s",s1);x=rd();
        scanf("%s",s2);y=rd();
        if(s1[0]==s2[0]){ans+=fabs(x-y);continue;}
        a[++tt].x=x;a[tt].y=y;a[tt].val=(x+y)*.5;
        v[++nn]=x;v[++nn]=y;
    }
    if(!tt)return void(printf("%lld\n",ans));
    ans+=tt;
    sort(v+1,v+nn+1);nn=unique(v+1,v+nn+1)-v-1;
    fo(i,1,tt){
        a[i].x=lower_bound(v+1,v+nn+1,a[i].x)-v;
        a[i].y=lower_bound(v+1,v+nn+1,a[i].y)-v;
        c[a[i].x]++;c[a[i].y]++;
    }
    sort(a+1,a+tt+1,cmp);
    Seg::build(rt,1,nn);
    ll mn=Inf,tmp;pii res;
//  fo(i,1,tt)printf("%d %d %.2lf\n",a[i].x,a[i].y,a[i].val);
//  fo(i,1,nn)printf("%d ",v[i]);puts("");
    fo(i,1,tt){
        Seg::modify(rt,1,nn,a[i].x);
        Seg::modify(rt,1,nn,a[i].y);
         
        tmp=0;sz[0]=sz[1]=sm[0]=sm[1]=0;
        x=Seg::querys(rt,1,nn,i,0);
        tmp+=sz[0]*x-sm[0]+sm[1]-x*sz[1];
         
        if(i!=tt){
            sz[0]=sz[1]=sm[0]=sm[1]=0;
            x=Seg::querys(rt,1,nn,tt-i,1);
            tmp+=sz[0]*x-sm[0]+sm[1]-x*sz[1];
        }
        mn=min(tmp,mn);
    }
    ans+=mn;
    printf("%lld\n",ans);
}
 
}
 
int main()
{
    open("c");
    K=rd();n=rd();
    if(K==1)K1::gao();
    else K2::gao();
    return 0;
}
posted @ 2018-10-23 16:29  Jackyhh  阅读(120)  评论(1编辑  收藏  举报