zoukankan      html  css  js  c++  java
  • 【BZOJ4071】八邻旁之桥(线段树)

    【BZOJ4071】八邻旁之桥(线段树)

    题面

    BZOJ权限题,洛谷链接

    题解

    既然(k<=2)
    那么,突破口就在这里

    分类讨论
    (k=1)
    这。。。不就是中位数吗。。。。
    直接把所有起点重点排个序,
    算下中位数就行啦
    (k=2)
    似乎不好搞了
    orz ZSY Dalao
    我太弱了
    我就是一个Vegetable Chicken
    ZSY看一眼就会做

    补充:ZSY大佬提醒我,Bridge我写错了
    所以:#define Brige Bridge

    首先,我们来看一看,如果有两座桥,
    一个人会怎么动呢?
    如果桥在他所移动的横向区间内
    那么,一定会过这座桥,距离为(dis(Qi-Ti)+1)
    如果,没有桥在他的区间内
    他就要先走到桥,再从桥走过来
    此时距离为(abs(Qi-Brige)+abs(Ti-Brige)+1)
    这个东西再结合图像化个简
    等于(2abs(frac{Qi+Ti}{2}-Brige)+1)
    所以,这个人走的桥一定是离(frac{Qi+Ti}{2})较近的桥

    因此,把所有人按照(frac{Qi+Ti}{2})排序之后
    开始枚举在哪个位置割开
    然后左边的都走左边的桥
    右边的都走右边的桥
    拆成了两边之后就是(k=1)的情况了
    但是因为是动态维护区间的中位数
    所以要找个东西来维护
    权值线段树,平衡树都是可以的

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define MAX 250000
    #define lson (now<<1)
    #define rson (now<<1|1)
    inline int read()
    {
    	int x=0,t=1;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return x*t;
    }
    struct Node{int a,b;}w[MAX];
    bool operator<(Node a,Node b){return a.a+a.b<b.a+b.b;} 
    int cnt;
    long long ans;
    int K,n,a[MAX],b[MAX],S[MAX],top;
    struct SegMentTree
    {
    	struct node
    	{
    		int size;ll sum;
    	}t[MAX<<2];
    	int Kth(int now,int l,int r,int k)
    		{
    			if(l==r)return l;
    			int mid=(l+r)>>1;
    			if(k<=t[lson].size)return Kth(lson,l,mid,k);
    			else return Kth(rson,mid+1,r,k-t[lson].size);
    		}
    	void Modify(int now,int l,int r,int pos,int ww)
    		{
    			t[now].size+=ww;t[now].sum+=1ll*ww*S[pos];
    			if(l==r)return;
    			int mid=(l+r)>>1;
    			if(pos<=mid)Modify(lson,l,mid,pos,ww);
    			else Modify(rson,mid+1,r,pos,ww);
    		}
    	ll QueryV(int now,int l,int r,int al,int ar)
    		{
    			if(al<=l&&r<=ar)return t[now].sum;
    			int mid=(l+r)>>1;ll ret=0;
    			if(al<=mid)ret+=QueryV(lson,l,mid,al,ar);
    			if(ar>mid)ret+=QueryV(rson,mid+1,r,al,ar);
    			return ret;
    		}
    	int QueryS(int now,int l,int r,int al,int ar)
    		{
    			if(al<=l&&r<=ar)return t[now].size;
    			int mid=(l+r)>>1,ret=0;
    			if(al<=mid)ret+=QueryS(lson,l,mid,al,ar);
    			if(ar>mid)ret+=QueryS(rson,mid+1,r,al,ar);
    			return ret;
    		}
    }T[2];
    int main()
    {
    	K=read();n=read();
    	char ch[2];
    	if(K==1)
    	{
    		int tot=0;
    		for(int i=1;i<=n;++i)
    		{
    			scanf("%s",ch);int p=ch[0]-'A';
    			int s=read();
    			scanf("%s",ch);int q=ch[0]-'A';
    			int t=read();
    			if(p==q){ans+=abs(s-t);continue;}
    			else if(p==1)swap(s,t);
    			++tot;a[tot]=s;b[tot]=t;S[++top]=s;S[++top]=t;
    		}
    		sort(&S[1],&S[top+1]);
    		int G=S[top/2];
    		for(int i=1;i<=top;++i)ans+=abs(G-S[i]);
    		printf("%lld
    ",ans+tot);
    		return 0;
    	}
    	for(int i=1;i<=n;++i)
    	{
    		scanf("%s",ch);int p=ch[0]-'A';
    		int s=read();
    		scanf("%s",ch);int q=ch[0]-'A';
    		int t=read();
    		if(p==q){ans+=abs(s-t);continue;}
    		ans++;S[++top]=s;S[++top]=t;
    		if(s>t)swap(s,t);
    		w[++cnt]=(Node){s,t};
    	}
    	if(!cnt){printf("%lld
    ",ans);return 0;}
    	sort(&w[1],&w[cnt+1]);
    	sort(&S[1],&S[top+1]);
    	top=unique(&S[1],&S[top+1])-S-1;
    	for(int i=1;i<=cnt;++i)
    	{
    		w[i].a=lower_bound(&S[1],&S[top+1],w[i].a)-S;
    		w[i].b=lower_bound(&S[1],&S[top+1],w[i].b)-S;
    		T[1].Modify(1,1,top,w[i].a,1);
    		T[1].Modify(1,1,top,w[i].b,1);
    	}
    	long long sum=1e18;
    	for(int i=1;i<=cnt;++i)
    	{
    		T[0].Modify(1,1,top,w[i].a,1);
    		T[0].Modify(1,1,top,w[i].b,1);
    		T[1].Modify(1,1,top,w[i].a,-1);
    		T[1].Modify(1,1,top,w[i].b,-1);
    		int p1=T[0].Kth(1,1,top,i);//找中位数
    		int p2=T[1].Kth(1,1,top,cnt-i);
    		long long D0=0;
    		D0+=1ll*T[0].QueryS(1,1,top,1,p1)*S[p1]-T[0].QueryV(1,1,top,1,p1);
    		D0+=T[0].QueryV(1,1,top,p1,top)-1ll*T[0].QueryS(1,1,top,p1,top)*S[p1];
    		long long D1=0;
    		D1+=1ll*T[1].QueryS(1,1,top,1,p2)*S[p2]-T[1].QueryV(1,1,top,1,p2);
    		D1+=T[1].QueryV(1,1,top,p2,top)-1ll*T[1].QueryS(1,1,top,p2,top)*S[p2];
    		sum=min(sum,D0+D1);
    	}
    	printf("%lld
    ",ans+sum);
    	return 0;
    }
    
    
  • 相关阅读:
    codeforces 980A Links and Pearls
    zoj 3640 Help Me Escape
    sgu 495 Kids and Prizes
    poj 3071 Football
    hdu 3853 LOOPS
    hdu 4035 Maze
    hdu 4405 Aeroplane chess
    poj 2096 Collecting Bugs
    scu 4444 Travel
    zoj 3870 Team Formation
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8206937.html
Copyright © 2011-2022 走看看