计蒜客某赛G(单调队列)

不造怎么描述题目来源了。。。直接给链接

https://nanti.jisuanke.com/t/26156

很明显选择从第一类边进去之后就只能走第二类边了,那问题就是选择哪个点作为中转点了。。

对任意点i来说,d=0时的路径长度和边数都是确定的,那么可以确定路径和d的函数关系,事实上就是一次函数的关系了。。

然后就是如何对每次询问,找到最小的函数值了。。

汪聚告诉窝萌,这些函数可以在图上表示成若干直线,那么就可以维护一个上凸包了。。

维护的具体方法就是,将这些直线依次加入单调队列,显然队列里面的斜率是单调递减的,然后直线集能形成如下的上凸包。。



事实上只要斜率递减即可入队。。

然后通过与倒数第二条直线的交点的x1坐标和倒数第二条直线和队尾直线交点x2坐标判断是否把队尾踢出队列。。

如下x1>x2,不踢出


而如下x1<x2,踢出




然后将询问离散化一下。。随着d的增加逐渐踢出队头。。。




/**
 *        ┏┓    ┏┓
 *        ┏┛┗━━━━━━━┛┗━━━┓
 *        ┃       ┃  
 *        ┃   ━    ┃
 *        ┃ >   < ┃
 *        ┃       ┃
 *        ┃... ⌒ ...  ┃
 *        ┃       ┃
 *        ┗━┓   ┏━┛
 *          ┃   ┃ Code is far away from bug with the animal protecting          
 *          ┃   ┃   神兽保佑,代码无bug
 *          ┃   ┃           
 *          ┃   ┃        
 *          ┃   ┃
 *          ┃   ┃           
 *          ┃   ┗━━━┓
 *          ┃       ┣┓
 *          ┃       ┏┛
 *          ┗┓┓┏━┳┓┏┛
 *           ┃┫┫ ┃┫┫
 *           ┗┻┛ ┗┻┛
 */ 
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-12
#define succ(x) (1<<x)
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid (x+y>>1)
#define NM 200005
#define nm 200005
#define pi 3.1415926535897931
using namespace std;
const ll inf=100000000000000005;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}




struct line{
	ll k,b;
	bool operator<(const line&o){return b<o.b;}
}q[NM],c[NM];
struct tmp{
	ll x;int i;
	bool operator<(const tmp&o){return x<o.x;}
}p[NM];


ll ans[NM];
int n,qt,qh,m;
ll a[NM],b[NM];

bool slope(line a,line b,line c){return (a.b-b.b)*(a.k-c.k)<(a.b-c.b)*(a.k-b.k);}

int main(){
	int _=read();
	while(_--){
		n=read();m=read();mem(ans);mem(q);mem(c);mem(p);mem(b);mem(a);
		inc(i,2,n)a[i]=read();
		inc(i,2,n-1)b[i]=read();
		dec(i,n-1,2)b[i]+=b[i+1];
		inc(i,1,n-1)c[i].k=n-i,c[i].b=b[i+1]+a[i+1];
		sort(c+1,c+n);
		qh=1;qt=0;
		inc(i,1,n-1){
			if(qh<=qt&&c[i].k>=q[qt].k)continue;
			while(qh<qt&&slope(q[qt-1],q[qt],c[i]))qt--;
			q[++qt]=c[i];
		}
		inc(i,1,m)p[i].x=read(),p[i].i=i;
		sort(p+1,p+1+m);
		inc(i,1,m){
			while(qh<qt&&q[qh].k*p[i].x+q[qh].b>q[qh+1].k*p[i].x+q[qh+1].b)qh++;
			ans[p[i].i]=q[qh].k*p[i].x+q[qh].b;
		}
		inc(i,1,m-1)printf("%lld ",ans[i]);printf("%lld\n",ans[m]);
	}
	return 0;
}





Trouble of Tyrant

Description:

Tyrant has a private island on the Pacific Ocean. He has built many luxury villas on the island. He flies here every vacation to enjoy life. He will drive his sports car between his villas. Tyrant has n villas on the island and the last villa which is numbered by n is his favorite. His money is only allowed to build one airpor located at the first villa which is numbered by 1 so every time he come to the island, he will land at the villa numbered 1. What's more Tyrant build 2*n-3 roads on the island. For every villa except the first island, there is a two-way street connecting this villa and the first villa. For every villa numbered by i (i >= 3) there is a two-way street connecting this villa and the villa numbered by i - 1. Tyrant is not satisfied, he think the road is not long enough. He asks q problems, every problem has a non negative integer d. He want to know if the length of each road is increaced by d what is the shortest distance between the first villa and his favorite villa. Notice that the increment in each problem is not cumulative -- in other words it doesn't take effect on the real road after query.

Input:

The first integer indicate the number of test cases T (T <= 10).

In each test cases the first line contains two integers n and q -- the number of villas and the number of queries (3 <= n <= 100000, 1 <= q <= 100000).

The second line contains n - 1 non-negative integers -- ai describe a road with length ai connecting villa 1 and i (2 <= i <= n)

The third line contains n - 2 non-negative integers -- bi describe a road with length bi connecting villa i - 1 and i (3 <= i <= n)

The next line contains q non-negative integers -- di means Tyrant want to know what is the shortest distance between the first villa ans his favorite villa when the length of each road is increaced by di.

All integers are 32-bit signed integer.

Output:

For each test case you should output q integers in one line means the answer for each problem.

样例输入

1
3 3
1 5
2
0 2 4

样例输出

3 7 9

题目来源

2018 ACM-ICPC 中国大学生程序设计竞赛线上赛


猜你喜欢

转载自blog.csdn.net/qkoqhh/article/details/80050987