您的位置:首页 > 其它

4515: [Sdoi2016]游戏

2016-08-18 20:41 405 查看

4515: [Sdoi2016]游戏

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 396  Solved: 178

[Submit][Status][Discuss]

Description

Alice 和 Bob 在玩一个游戏。
游戏在一棵有 n 个点的树上进行。最初,每个点上都只有一个数字,那个数字是 123456789123456789。
有时,Alice 会选择一条从 s 到 t 的路径,在这条路径上的每一个点上都添加一个数字。对于路径上的一个点 r,
若 r 与 s 的距离是 dis,那么 Alice 在点 r 上添加的数字是 a×dis+b。有时,Bob 会选择一条从 s 到 t 的路径。
他需要先从这条路径上选择一个点,再从那个点上选择一个数字。
Bob 选择的数字越小越好,但大量的数字让 Bob 眼花缭乱。Bob 需要你帮他找出他能够选择的最小的数字。

Input

第一行两个数字 n、m,表示树的点数和进行的操作数。
接下来 n−1 行,每行三个数字 u、v、w,表示树上有一条连接 u、v 的边,长度是 w。
接下来 m 行。每行第一个数字是 1 或 2。
若第一个数是 1,表示 Alice 进行操作,接下来四个数字 s、t、a、b。
若第一个数是 2,表示 Bob 进行操作,接下来四个数字 s、t。

Output

每当 Bob 进行操作,输出一行一个数,表示他能够选择的最小的数字

Sample Input

3 5

1 2 10

2 3 20

2 1 3

1 2 3 5 6

2 2 3

1 2 3 -5 -6

2 2 3

Sample Output

123456789123456789

6

-106

HINT

 n≤100000,m≤100000,∣a∣≤10000,0<=w,|b|<=10^9

Source

鸣谢Menci上传

[Submit][Status][Discuss]

今天算是栽在这上面了,,日,,细节真多
总体思路显然:树链剖分+李超树
从s到Lca一段,从Lca到t一段
可分别用不同的斜率和截距表示,便于处理
即将原数据稍加修改得(详见代码)
然后是,,维护一个区间最低点
更新时刻有:
本区间被新线段覆盖
更新了子区间
记得更新区间最低点时不能舍去以前的点

查询答案的时候,从上往下一边找最低点一边用覆盖区间的线段尝试更新


日啊,,,调了半天,,真的是半天(from 12:00 to 20:30)
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;

const int maxn = 1E5 + 10;
const int T = 20;
typedef long long LL;
const LL Inf = 123456789123456789;
typedef double DB;

struct E{
int to,w;
E (int _to = 0,int _w = 0) {to = _to; w = _w;}
};

int n,m,cnt,Root,Lca,I,fa[maxn][20],len[maxn],Nex[maxn],L[maxn]
,First[maxn],pos[maxn],siz[maxn],root[maxn],lc[maxn*T],rc[maxn*T];
LL ans,Min[maxn*T],Light[maxn],k[maxn*T],b[maxn*T],dis2[maxn],dis[maxn];
bool Huge[maxn];

vector <E> v[maxn];
vector <int> Road[maxn];

int New() {++cnt; k[cnt] = 0; b[cnt] = Min[cnt] = Inf; return cnt;}
int Getlc(int o) {return lc[o]?lc[o]:lc[o] = New();}
int Getrc(int o) {return rc[o]?rc[o]:rc[o] = New();}

void dfs(int x,int from)
{
Light[x] = Inf;
siz[x] = 1; int Max = 0,po;
for (int i = 1; i < 20; i++) fa[x][i] = fa[fa[x][i-1]][i-1];
for (int i = 0; i < v[x].size(); i++) {
int to = v[x][i].to;
if (to == from) continue;
fa[to][0] = x; dis[to] = dis[x] + 1LL*v[x][i].w;
L[to] = L[x] + 1; dfs(to,x);
siz[x] += siz[to];
if (siz[to] > Max) Max = siz[to],po = to;
}
if (siz[x] > 1) Huge[po] = 1,Nex[x] = po;
}

void dfs2(int x,int from,int Len)
{
if (siz[x] == 1) {
if (Huge[x]) {
len[x] = Len + 1; First[x] = x;
root[x] = New(); pos[x] = 1;
k[cnt] = 0; b[cnt] = Inf;
dis2[x] = 0;
Road[x].push_back(0);
Road[x].push_back(x);
}
return;
}
Len = Huge[x]?++Len:0;
for (int i = 0; i < v[x].size(); i++) {
int to = v[x][i].to;
if (to == from) continue;
dfs2(to,x,Len);
}
if (Huge[x]) {
root[x] = root[Nex[x]]; len[x] = len[Nex[x]]; First[x] = First[Nex[x]];
pos[x] = pos[Nex[x]] + 1; dis2[x] = dis2[Nex[x]] + dis[Nex[x]] - dis[x];
Road[First[x]].push_back(x);
}
}

void pushdown(int o,int belong,int l,int r,LL K,LL B)
{
int numl = Road[belong][l];
int numr = Road[belong][r];
LL A1 = dis2[numl]*K + B,A2 = dis2[numl]*k[o] + b[o];
LL B1 = dis2[numr]*K + B,B2 = dis2[numr]*k[o] + b[o];
Min[o] = min(Min[o],min(A1,B1));
if (A1 < A2 && B1 < B2) {
Min[o] = min(Min[o],min(A1,B1));
k[o] = K; b[o] = B;
return;
}
if (A1 >= A2 && B1 >= B2) return;
DB x = (DB)(b[o] - B)/(DB)(K - k[o]);
int Mid = Road[belong][(l+r)>>1]; LL mid = dis2[Mid]; Mid = pos[Mid];
if (x <= mid) {
if (A1 > A2) pushdown(Getlc(o),belong,l,Mid,k[o],b[o]),k[o] = K,b[o] = B;
else pushdown(Getlc(o),belong,l,Mid,K,B);
}
else {
if (A1 > A2) pushdown(Getrc(o),belong,Mid+1,r,K,B);
else pushdown(Getrc(o),belong,Mid+1,r,k[o],b[o]),k[o] = K,b[o] = B;
}
Min[o] = min(Min[o],min(Min[Getlc(o)],Min[Getrc(o)]));
}

void modify(int o,int belong,int l,int r,int ml,int mr,LL K,LL B)
{
if (ml <= l && r <= mr) {pushdown(o,belong,l,r,K,B); return;}
int mid = (l + r) >> 1;
if (ml <= mid) modify(Getlc(o),belong,l,mid,ml,mr,K,B);
if (mr > mid) modify(Getrc(o),belong,mid+1,r,ml,mr,K,B);
Min[o] = min(Min[o],min(Min[Getlc(o)],Min[Getrc(o)]));
}

int Quickfa(int x,int y)
{
for (int num = 0; y; y >>= 1,++num)
if (y & 1) x = fa[x][num];
return x;
}

void Modify1(int x,LL K,LL B)
{
LL Dis = 0;
for (; x != Lca; Dis += (dis[x] - dis[fa[x][0]]),x = fa[x][0]) {
if (!Huge[x]) Light[x] = min(Light[x],K*Dis + B);
else {
if (pos[x] == 1) {
if (L[x] - (len[x] - pos[x]) > L[Lca]) {
modify(root[x],First[x],1,len[x],pos[x],len[x],K,B+Dis*K);
Dis += dis[x];
x = Quickfa(x,len[x] - pos[x]);
Dis -= dis[x];
}
else {
modify(root[x],First[x],1,len[x],pos[x],pos[Lca]-1,K,B+Dis*K);
return;
}
}
else {
if (L[x] - (len[x] - pos[x]) > L[Lca]) {
modify(root[x],First[x],1,len[x],pos[x],len[x],K,B+(Dis-dis2[x])*K);
Dis += dis[x];
x = Quickfa(x,len[x] - pos[x]);
Dis -= dis[x];
}
else {
modify(root[x],First[x],1,len[x],pos[x],pos[Lca]-1,K,B+(Dis-dis2[x])*K);
return;
}
}
}
}
}

void Modify2(int x,LL K,LL B,LL Dis)
{
Dis += (dis[x] - dis[Lca]);
for (; x != Lca; Dis -= (dis[x] - dis[fa[x][0]]),x = fa[x][0]) {
if (!Huge[x]) Light[x] = min(Light[x],K*Dis + B);
else {
if (pos[x] == 1) {
if (L[x] - (len[x] - pos[x]) > L[Lca]) {
modify(root[x],First[x],1,len[x],pos[x],len[x],-K,B+Dis*K);
Dis -= dis[x];
x = Quickfa(x,len[x] - pos[x]);
Dis += dis[x];
}
else {
modify(root[x],First[x],1,len[x],pos[x],pos[Lca]-1,-K,B+Dis*K);
return;
}
}
else {
if (L[x] - (len[x] - pos[x]) > L[Lca]) {
modify(root[x],First[x],1,len[x],pos[x],len[x],-K,B+(Dis+dis2[x])*K);
Dis -= dis[x];
x = Quickfa(x,len[x] - pos[x]);
Dis += dis[x];
}
else {
modify(root[x],First[x],1,len[x],pos[x],pos[Lca]-1,-K,B+(Dis+dis2[x])*K);
return;
}
}
}
}
}

LL query(int o,int belong,int l,int r,int ql,int qr)
{
LL QL = Road[belong][max(ql,l)]; QL = dis2[QL];
LL QR = Road[belong][min(qr,r)]; QR = dis2[QR];
LL A1 = QL*k[o] + b[o];
LL B1 = QR*k[o] + b[o];
if (ql <= l && r <= qr) return min(Min[o],min(A1,B1));
int mid = (l + r) >> 1;
LL ret = Inf;
if (ql <= mid) ret = min(ret,query(Getlc(o),belong,l,mid,ql,qr));
if (qr > mid) ret = min(ret,query(Getrc(o),belong,mid+1,r,ql,qr));
return min(ret,min(A1,B1));
}

void Query(int x)
{
for (; x != Lca; x = fa[x][0]) {
if (!Huge[x]) ans = min(ans,Light[x]);
else {
if (L[x] - (len[x] - pos[x]) > L[Lca]) {
ans = min(ans,query(root[x],First[x],1,len[x],pos[x],len[x]));
x = Quickfa(x,len[x] - pos[x]);
}
else {
ans = min(ans,query(root[x],First[x],1,len[x],pos[x],pos[Lca]-1));
return;
}
}
}
}

int getint()
{
char ch = getchar();
int ret = 0,multi = 1;
while (ch < '0' || '9' < ch) {
if (ch == '-') multi = -1;
ch = getchar();
}
while ('0' <= ch && ch <= '9') ret = ret*10 + ch - '0',ch = getchar();
return ret*multi;
}

int LCA(int p,int q)
{
if (L[p] < L[q]) swap(p,q);
int Log; for (Log = 0; L[p] - (1<<Log) >= 1; Log++); --Log;
for (int j = Log; j >= 0; j--)
if (L[p] - (1<<j) >= L[q])
p = fa[p][j];
if (p == q) return p;
for (int j = Log; j >= 0; j--)
if (fa[p][j] != fa[q][j])
p = fa[p][j],q = fa[q][j];
return fa[p][0];
}

int main()
{
#ifdef DMC
//freopen("DMC.txt","r",stdin);
freopen("game20.in","r",stdin);
freopen("test.txt","w",stdout);
#endif

n = getint(); m = getint();
for (int i = 1; i < n; i++) {
int x = getint(),y = getint(),z = getint();
v[x].push_back(E(y,z));
v[y].push_back(E(x,z));
}
Root = n/2; L[Root] = 1;
dfs(Root,0); dfs2(Root,0,0);
for (I = 1; I <= m; I++) {
int typ = getint(),s = getint(),t = getint();
Lca = LCA(s,t);
if (typ == 1) {
LL K = getint(),B = getint();
if (Lca != s) Modify1(s,K,B);
if (!Huge[Lca]) Light[Lca] = min(Light[Lca],(dis[s] - dis[Lca])*K + B);
else {
DB NewB = (dis[s] - dis[Lca] - dis2[Lca])*K+B;
modify(root[Lca],First[Lca],1,len[Lca],pos[Lca],pos[Lca],K,NewB);
}
if (Lca != t) Modify2(t,K,B,dis[s] - dis[Lca]);
}
else {
ans = Inf;
if (s != Lca) Query(s);
if (t != Lca) Query(t);
if (!Huge[Lca]) ans = min(ans,Light[Lca]);
else ans = min(ans,query(root[Lca],First[Lca],1,len[Lca],pos[Lca],pos[Lca]));
printf("%lld\n",ans);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: