有乙個n個點的無向圖,給出m條邊,每條邊的資訊形如題解:y,c,
r>
給出q組詢問形如
v,l,
r>
接下來解釋詢問以及邊的意義。
詢問表示,一開始你在點u上,然後按順序處理編號從
1 到
r的邊。
對於一條邊
y,c,
r>
,你可以進行兩次操作:
1、如果你當前在
x 點或者
y點上,那麼你可以走這條邊(從
x 到y或從
y 到
x)並付出
c 的代價(當然你也可以不走,看操作
2)。
2、如果你不走這條邊或者不可以走這條邊(即你當前不在
x 或
y上),那麼你需要付出
r 的代價。
詢問如果要從點
u開始,按順序處理完編號從
l 到
r的邊之後到達點
v 的最小代價,如果不能到達
v,那麼輸出
−1n≤
30,m≤
20000,q
≤200000
樸素的分塊做法:
將邊分成若干連續塊, f[
i][k
][j]
表示i 經過第
k塊中的所有邊到達
j 的最小代價,每次詢問暴力dp,複雜度o(
n2m−
−√⋅q
),可以卡過60分。
code:
分塊的瓶頸:依然不能高效整合區間,只能選擇折中的辦法。
進一步發現許多區間重複處理了很多次,如果能將這些區間接近的詢問合併到一起dp會更優,於是就有了分治的做法:
對於每個分治點中心,先處理所有在中心點左邊和右邊的詢問,並維護值f[
i][j
][l]
表示從i 到j經過
l 到mi
d的邊的最小代價,同樣維護處右邊到終點的代價,再處理中間的詢問即可。
時間複雜度o(
mlogm⋅
n2+n
⋅q)
#include
typedef
long
long ll;
using
namespace
std;
inline
int read()
while(isdigit(ch))
return i*f;
}inline
void w(int x)
if(x<0)
while(x)
while(buf[0])
return;
}const
int maxn=35,maxm=2e4+50,maxq=2e5+50,inf=0x7fffffff;
int n,m,q;
ll tm[maxm][maxn][maxn],mt[maxm][maxn][maxn],ans[maxq];
struct eedge[maxm];
struct q;
vector
qry_pos[maxm<<2];
inline
void solve(int k,int l,int r)
for(int e=qry_pos[k].size()-1;e>=0;e--)
}else
if(l!=mid)
}else
if(r!=mid)
}else
ans[qry.id]=res;
}if(l==r)
if(i==edge[l].y)
}}else
mt[i][j][k]=mt[i-1][j][k]+edge[i].r;
if(edge[i].y==k)mt[i][j][k]=min(mt[i][j][k],mt[i-1][j][edge[i].x]+edge[i].c);
if(edge[i].x==k)mt[i][j][k]=min(mt[i][j][k],mt[i-1][j][edge[i].y]+edge[i].c);}}
} }else
tm[i][j][k]=tm[i+1][j][k]+edge[i].r;
if(edge[i].y==j)tm[i][j][k]=min(tm[i][j][k],tm[i+1][edge[i].x][k]+edge[i].c);
if(edge[i].x==j)tm[i][j][k]=min(tm[i][j][k],tm[i+1][edge[i].y][k]+edge[i].c);}}
}}
}}int main()
for(int i=1;i<=q;i++));
break;
}(r1,r=mid-1):(k=k<<1|1,l=mid+1);}}
solve(1,1,m);
for(int i=1;i<=q;i++)w((ans[i]>=inf?-1:ans[i])),putchar('\n');
}
NOIP模擬 字元處理(送分or送命?)
媽媽的工作是英語翻譯,經常和英語字串打交道,今天媽媽給了 tom 乙個只有小寫字 母構成的字串,需要 tom 做以下工作 要是連續出現相同的小寫字母,則把他們替換成這個字母的大寫形式,後面緊跟相同字 母的個數,並把它之前跟之後的兩段字串調換,例如出現 bcaaaaaaef,則新字串變成 efa6bc...
NOIP模擬 字元處理(送分or送命?)
媽媽的工作是英語翻譯,經常和英語字串打交道,今天媽媽給了 tom 乙個只有小寫字 母構成的字串,需要 tom 做以下工作 要是連續出現相同的小寫字母,則把他們替換成這個字母的大寫形式,後面緊跟相同字 母的個數,並把它之前跟之後的兩段字串調換,例如出現 bcaaaaaaef,則新字串變成 efa6bc...
NOIP校內模擬 T2 字胡串(分治)
lst神仙 這是他的做法 吊了標算 對於這種有多少區間滿足要求的 我們套路的用分治做 每次都統計左端點在左半邊 右端點在右半邊的個數 設f i 表示當前點到中間分割點的最大值,g i 表示當前點到中間分割點的或和 我們發現 g i f i 所以只需找到g i f i 的區間就好 然後f肯定是單調遞增...