BZOJ4071: [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$ 的最小值。
输入输出样例
说明
【数据范围】
所有数据都保证:$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|\text{位置}-\text{中位数}|$。
附代码:(我分了两个$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\n",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\n",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\n",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;
}

浙公网安备 33010602011771号