紀中集訓2019 3 21 橋

2022-04-06 12:55:26 字數 3931 閱讀 7940

描述

有\(m\)條河,每條河的兩邊有居民點,所以共有\(m+1\)排居名點;

如果要從一排居名點到另一排相鄰的居民點需要過河;

現在有\(n\)個人,每個人的起點座標是\((p_,s_)\),終點\((q_,t_)\);

你可以在每條河上修建一座橋,過河必須通過橋;

相鄰居民點距離為\(1\),不考慮過河的時間;

問\(n\)個人到終點的路徑之和最小是多少;

範圍\(1 \le n , m \le 10^5 \ , \ 1 \le s_ ,t_ \le 10^9 ,\ 1 \le p_,q_ \le m+1\)

題解:\[\begin

f_ &= g_(j) \ \ &(i=1) \\

f_ &= min \ \ + \ b_ |a_-a_| \ + \ g_(j) \} \ \ &(i \gt 1) \\

\end

\]所以得到乙個\(o(n^2m)\)的\(dp\),可以用單調佇列簡單優化到\(o(nm)\);

\(g_\)一定是凸函式,所以\(f_\)一定是凸的,同時由於凸函式對加法封閉,所以直接考慮轉移前半部分:

考慮在\(f_\)上找到兩個斜率為 \(-b_\) 和\(b_\)的點設為\(j1和j2\)

\[f_ = g_(j) +

\begin

&f_ &+& b_ |a_-a_| &(j \lt j1)\\

&f_ &+ &b_ |a_-a_| &(j1 \le j \le j2)\\

&f_ &+ &b_ |a_-a_| &(j2 \lt j)\\

\end

\](分析絕對值簡單比較就可以得到)

所以\(f_ \to f_\)就是區間賦值一次函式,區間加一次函式,所以\(f_\)仍然是凸的;

用線段樹或者\(set\)維護差分即可;

注意要另外維護一下\(f_\) ;

#include#define pb push_back

#define mk make_pair

#define ls (k<<1)

#define rs (k<<1|1)

#define ll long long

#define inf 1e18

#define il inline

using namespace std;

const int n=100010;

int n,m,tot,sub[n<<1],p[n],s[n],q[n],t[n];

vectora[n];

ll b,sum[n],b[n],ans;

il char gc()

il int rd()

ll s[n<<3],d[n<<3],dr[n<<3],ly1[n<<3],ly2[n<<3];

il void build(int k,int l,int r)

int mid=l+r>>1;

build(ls,l,mid);

build(rs,mid+1,r);

}il void mfy1(int k,int l,int r,ll x)

il void mfy2(int k,int l,int r,ll x)

il void pushup(int k,int l,int r)

il void pushdown(int k,int l,int r)

if(ly1[k])

}void update1(int k,int l,int r,int x,int y,ll v)

int mid=(l+r)>>1;

pushdown(k,l,r);

if(y<=mid)update1(ls,l,mid,x,y,v);

else if(x>mid)update1(rs,mid+1,r,x,y,v);

else update1(ls,l,mid,x,mid,v),update1(rs,mid+1,r,mid+1,y,v);

pushup(k,l,r);

}void update2(int k,int l,int r,int x,int y,ll v)

int mid=(l+r)>>1;

pushdown(k,l,r);

if(y<=mid)update2(ls,l,mid,x,y,v);

else if(x>mid)update2(rs,mid+1,r,x,y,v);

else update2(ls,l,mid,x,mid,v),update2(rs,mid+1,r,mid+1,y,v);

pushup(k,l,r);

}int query1(int k,int l,int r,ll x)

ll query2(int k,int l,int r,int x,int y)

il void update1(int cur)

sub[++tot]=1;

sort(sub+1,sub+tot+1);

tot=unique(sub+1,sub+tot+1)-sub-1;

for(int i=1;i<=n;++i)

a[l+1].pb(s[i]);sum[l+1]+=sub[s[i]]-1;

a[r].pb(t[i]);sum[r]+=sub[t[i]]-1;

b[l+2]++,b[r+1]--;

} build(1,0,tot);

update1(1);

for(int i=2;i<=m;++i)

int pos=query1(1,0,tot,0);

if(pos>1)ans+=query2(1,0,tot,1,pos-1);

printf("%lld\n",ans);

return 0;

}

//這是fxy寫的set;

#pragma gcc optimize(3)

#include#include#include#include#include#include#include#include#define rg register

#define ll long long

#define ldb long double

#define ull unsigned long long

#define view(i,x) for(rg int i=hd[x];i!=-1;i=e[i].nt)

#define go(i,x,a) for(rg int i=a;ig[maxn];

multisets,t;

ll ans=0;

inline int rd()

while(gc >= '0' && gc <= '9') ret=ret*10+gc-'0',gc=getchar();

return ret*af;

}inline void update(int x)

if(x < l)else r=l;

s.insert(x); s.insert(x); t.insert(r);

return ;

} if(x > r)else l=r;

t.insert(x); t.insert(x); s.insert(l); }}

int main()

if(p > q) swap(p,q),swap(a,b);

g[p].push_back(a);

g[q-1].push_back(b);

if(p+1 <= q-1) f[p+1]++,f[q]--;

} go(i,m+1,1) f[i]+=f[i-1];

l=0; r=inf;

s.insert(l); t.insert(r);

go(i,m+1,1)

go(j,g[i].size(),0) update(g[i][j]);

} printf("%lld",ans);

return 0;

}

紀中集訓2019 11 05

題目鏈結 有 n 個點,求 n 1 個完美匹配,且其中不出現相同的邊。n le 10 3 打暴力 手玩找到規律。把匹配放到方格圖上,給屬於同乙個完美匹配的方格染上同樣的顏色,發現兩個性質 最後一列第一行填 n 之後往下從小到大填完偶數,再從小到大填完奇數 forall i in 1,n 1 從 1,...

紀中集訓 遊戲

題目鏈結 是紀中的題,不過我已經沒有紀中的號了,於是翻出了我的古早部落格 複習的時候又做了一遍,還是想了一會兒的,並且由衷地覺得這真是一道好題。考慮 sg 函式遞推。由於每次操作只能動最後一行和最後一列,那麼設 sg i,j 表示以 i,j 結尾的矩陣的 sg 函式值。轉移有 sg i,j mex ...

紀中集訓2019 3 25 染色問題

有乙個紙片,紙片上有 n 個格仔,初始時沒有顏色 某個遊戲的內容是進行 m 次染色,使得染完後 n 個格仔一定有顏色 每次可以選擇乙個區間 l,r l le r 去染 不能不染 顏色可以覆蓋 問最後染出的序列有多少種 n,m le 10 6 說正解 方程中存在兩類貢獻,一種是 f times j 1...