zoukankan      html  css  js  c++  java
  • BZOJ4071: [APIO2015]八邻旁之桥

    BZOJ4071: [APIO2015]八邻旁之桥

    这个题也变成了权限题,不是很懂为什么。。。

    反正没钱氪金。。。

    这里附上洛谷的题面:

    洛谷P3644 [APIO2015]八邻旁之桥

    题目描述

    一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 AA 和区域 BB。

    每一块区域沿着河岸都建了恰好$1000000001$栋的建筑,每条岸边的建筑都从$ 0$ 编号到 $1000000000$。相邻的每对建筑相隔 $1$ 个单位距离,河的宽度也是 $1$ 个单位长度。

    区域 $A$ 中的$ i$ 号建筑物恰好与区域 $B$ 中的 $i$ 号建筑物隔河相对。

    城市中有$ N$ 个居民。第 $i$ 个居民的房子在区域$ P_i$ 的$ S_i$号建筑上,同时他的办公室坐落在$ Q_i$ 区域的$ T_i$ 号建筑上。

    一个居民的房子和办公室可能分布在河的两岸,这样他就必须要搭乘船只才能从家中去往办公室,这种情况让很多人都觉得不方便。为了使居民们可以开车去工作,政府决定建造不超过 KK 座横跨河流的大桥。

    由于技术上的原因,每一座桥必须刚好连接河的两岸,桥梁必须严格垂直于河流,并且桥与桥之间不能相交。

    当政府建造最多$ K$ 座桥之后,设 $D_i$ 表示第$ i$ 个居民此时开车从家里到办公室的最短距离。请帮助政府建造桥梁,使得$ D_1 + D_2 + cdots + D_N$ 最小。

    输入输出格式

    输入格式:

    输入的第一行包含两个正整数$ K$ 和 $N$,分别表示桥的上限数量和居民的数量。

    接下来 NN 行,每一行包含四个参数:$P_i, S_i, Q_i$ 和$ T_i$,表示第$ i$ 个居民的房子在区域 $P_i$的$ S_i$ 号建筑上,且他的办公室位于 $Q_i$ 区域的 $T_i$ 号建筑上。

    输出格式:

    输出仅为一行,包含一个整数,表示$ D_1 + D_2 + cdots + D_N$ 的最小值。

    输入输出样例

    输入样例#1: 复制
    1 5
    B 0 A 4
    B 1 B 3
    A 5 B 7
    B 2 A 6
    B 1 A 7
    输出样例#1: 复制
    24
    
    输入样例#2: 复制
    2 5
    B 0 A 4
    B 1 B 3
    A 5 B 7
    B 2 A 6
    B 1 A 7
    输出样例#2: 复制
    22

    说明

    【数据范围】

    所有数据都保证:$P_i$ 和 $Q_i$ 为字符 “A” 和 “B” 中的一个, $0 leq S_i, T_i leq 1000000000$,同一栋建筑内可能有超过$ 1$ 间房子或办公室(或二者的组合,即房子或办公室的数量同时大于等于 $1$)。

    子任务 1 (8 分)$K = 1$

    $1 leq N leq 1000$

    子任务 2 (14 分)$K = 1$

    $1 leq N leq 100000$

    子任务 3 (9 分)$K = 2$

    $1 leq N leq 100$

    子任务 4 (32 分)$K = 2$

    $1 leq N leq 1000$

    子任务 5 (37 分)$K = 2$

    $1 leq N leq 100000$


    题解Here!

    又是一道把两个相似的题强行拼接在一起的题。。。
    直接分类讨论:
    当$k==1$的时候:
    如果工作地点在一侧,那么路程就是$r-l$。
    然后我们对于不在一侧的线段端点求个中位数,这样肯定能使总路程最小。
    不过,$k==1$的情况没有必要线段树,直接丢进数组里排个序,就可以求出中位数了。
    当$k==2$的时候:
    取每个线段的中点,如果靠近左边的桥,就往左边过桥,否则往右边过桥。
    枚举一个分割点,然后两边都是$k==1$的情况,用线段树求$sum| ext{位置}- ext{中位数}|$。
    附代码:(我分了两个$namespace$来写)

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define MAXN 1000010
    using namespace std;
    int n,k;
    int top=0,stack[MAXN];
    long long ans=0;
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline long long abs(const long long x){return x>0?x:-x;}
    namespace one{
    	int m=0;
    	void main(){
    		char ch[2];
    		int x,y,p,q;
    		for(int i=1;i<=n;i++){
    			scanf("%s",ch);x=read();p=ch[0]-'A';
    			scanf("%s",ch);y=read();q=ch[0]-'A';
    			if(p==q){
    				ans+=abs(x-y);
    				continue;
    			}
    			else if(p==1)swap(x,y);
    			m++;
    			stack[++top]=x;stack[++top]=y;
    		}
    		sort(stack+1,stack+top+1);
    		int mid=stack[top>>1];
    		for(int i=1;i<=top;i++)ans+=abs(mid-stack[i]);
    		printf("%lld
    ",ans+m);
    	}
    }
    namespace two{
    	#define LSON rt<<1
    	#define RSON rt<<1|1
    	#define DATA(rt) a[rt].data
    	#define SUM(rt) a[rt].sum
    	#define LSIDE(rt) a[rt].l
    	#define RSIDE(rt) a[rt].r
    	int num=0;
    	long long s[MAXN];
    	struct Line{
    		int x,y;
    		friend bool operator <(const Line &p,const Line &q){
    			return (p.x+p.y)<(q.x+q.y);
    		}
    	}line[MAXN];
    	struct Segment_Tree{
    		long long data,sum;
    		int l,r;
    	}a[MAXN<<2];
    	inline void add_line(int x,int y){
    		num++;
    		line[num].x=x;line[num].y=y;
    	}
    	inline void pushup(int rt){
    		DATA(rt)=DATA(LSON)+DATA(RSON);
    		SUM(rt)=SUM(LSON)+SUM(RSON);
    	}
    	void buildtree(int l,int r,int rt){
    		LSIDE(rt)=l;RSIDE(rt)=r;DATA(rt)=SUM(rt)=0;
    		if(l==r)return;
    		int mid=l+r>>1;
    		buildtree(l,mid,LSON);
    		buildtree(mid+1,r,RSON);
    	}
    	void update(int k,int v,int rt){
    		DATA(rt)++;SUM(rt)+=v;
    		if(LSIDE(rt)==RSIDE(rt))return;
    		int mid=LSIDE(rt)+RSIDE(rt)>>1;
    		if(k<=mid)update(k,v,LSON);
    		else update(k,v,RSON);
    	}
    	long long query(int k,int rt){
    		if(LSIDE(rt)==RSIDE(rt))return 1LL*stack[LSIDE(rt)]*k;
    		if(k<=DATA(LSON))return query(k,LSON);
    		else return SUM(LSON)+query(k-DATA(LSON),RSON);
    	}
    	inline long long ask(int x){return SUM(1)-2LL*query(x,1);}
    	void work(){
    		buildtree(1,top,1);
    		for(int i=1;i<=num;i++){
    			line[i].x=lower_bound(stack+1,stack+top+1,line[i].x)-stack;
    			line[i].y=lower_bound(stack+1,stack+top+1,line[i].y)-stack;
    			update(line[i].x,stack[line[i].x],1);
    			update(line[i].y,stack[line[i].y],1);
    			s[i]=ask(i);
    		}
    		long long minn=s[num];
    		buildtree(1,top,1);
    		for(int i=num;i>=1;i--){
    			update(line[i].x,stack[line[i].x],1);
    			update(line[i].y,stack[line[i].y],1);
    			minn=min(minn,s[i-1]+ask(num-i+1));
    		}
    		printf("%lld
    ",minn+ans);
    	}
    	void main(){
    		char ch[2];
    		int x,y,p,q;
    		for(int i=1;i<=n;i++){
    			scanf("%s",ch);x=read();p=ch[0]-'A';
    			scanf("%s",ch);y=read();q=ch[0]-'A';
    			if(p==q){
    				ans+=abs(x-y);
    				continue;
    			}
    			ans++;
    			stack[++top]=x;stack[++top]=y;
    			if(x>y)swap(x,y);
    			add_line(x,y);
    		}
    		if(!num){
    			printf("%lld
    ",ans);
    			return;
    		}
    		sort(line+1,line+num+1);
    		sort(stack+1,stack+top+1);
    		top=unique(stack+1,stack+top+1)-stack-1;
    		work();
    	}
    }
    int main(){
    	k=read();n=read();
    	if(k==1)one::main();
    	else two::main();
        return 0;
    }
    
  • 相关阅读:
    Python (time、datetime、random、os、sys、shutil)模块的使用
    ELK6+filebeat、kafka、zookeeper搭建文档
    JDBC-用Java语句操作数据库
    数据库对象
    sql之子查询
    函数之sql语句
    sql之select语句
    oracle 数据库
    网络编程
    多线程——多线程的运行轨迹,线程的生命周期,线程的常用方法,线程的安全问题,死锁,线程间的通信
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9657411.html
Copyright © 2011-2022 走看看