• 【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;
    }
    
    
  • 相关阅读:
    一道某高大上互联网公司的笔试题分享
    人机博弈-吃子棋游戏(四)搜索算法
    人机博弈-吃子棋游戏(三)走法生成
    人机博弈,吃子棋游戏(二)如何算气
    eclipse手动导入dtd文件
    spring BeanFactory概述
    xp的虚拟机如何访问本地主机上的文件
    XML Schema 简介
    DTD 简介
    spring开发相关网址
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8206937.html
Copyright © 2020-2023  润新知