日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【牛客NOIP模拟】 牛牛的RPG游戏【二维偏序】【任意坐标斜率优化】【CDQ 分治】【李超线段树】

發布時間:2023/12/3 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【牛客NOIP模拟】 牛牛的RPG游戏【二维偏序】【任意坐标斜率优化】【CDQ 分治】【李超线段树】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意: n×mn\times mn×m 的網格圖,每個點有兩個權值 vali,j,bufi,jval_{i,j},buf_{i,j}vali,j?,bufi,j?,從 (1,1)(1,1)(1,1) 開始只能向下或向右走到 (n,m)(n,m)(n,m) ,在某個位置時可以選擇觸發該位置的事件(也可不觸發),將獲得 vali,jval_{i,j}vali,j? 的得分和 bufi,jbuf_{i,j}bufi,j? 的 buff,該 buff 會在之后每一步產生對應的分數直到觸發下一個事件。求最大分數。

nm≤105nm\leq 10^5nm105,保證 val1,1=valn,m=buf1,1=bufn,m=0val_{1,1}=val_{n,m}=buf_{1,1}=buf_{n,m}=0val1,1?=valn,m?=buf1,1?=bufn,m?=0

顯然可以 dp,設 f(x,y)f(x,y)f(x,y) 為走到 (x,y)(x,y)(x,y) 并觸發事件的最大分數。

轉移枚舉上一個事件

f(x,y)=max?i≤x,j≤y{f(i,j)+buf(i,j)(x+y?i?j)}+val(i,j)f(x,y)=\max_{i\leq x,j\leq y}\{f(i,j)+buf(i,j)(x+y-i-j)\}+val(i,j)f(x,y)=ix,jymax?{f(i,j)+buf(i,j)(x+y?i?j)}+val(i,j)

顯然可以斜率優化

這個狀態有兩維,發現枚舉的位置是滿足二維偏序,所以可以 cdq 分治搞掉一維,另一維上李超線段樹即可。

注意 000?∞-\infin? 的不同。

復雜度 O(nmlog?2n)O(nm\log ^2n)O(nmlog2n)

#include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <vector> using namespace std; inline int read() {int ans=0,f=1;char c=getchar();while (!isdigit(c)) (c=='-')&&(f=-1),c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return f*ans; } const int N=2e5,MAXN=N+5,INF=2e9; int n,m; vector<int> val[MAXN],buf[MAXN],f[MAXN]; int k[MAXN],b[MAXN],tot; inline int calc(const int& i,const int& x){return k[i]*x+b[i];} int ch[MAXN][2],mx[MAXN],rt,cnt; inline void clear(){tot=0,rt=cnt=1,ch[1][0]=ch[1][1]=mx[1]=0;} void modify(int& p,int l,int r,int v) {if (!p) p=++cnt,ch[p][0]=ch[p][1]=mx[p]=0;if (!mx[p]) return (void)(mx[p]=v);if (calc(mx[p],l)>=calc(v,l)&&calc(mx[p],r)>=calc(v,r)) return;if (calc(mx[p],l)<=calc(v,l)&&calc(mx[p],r)<=calc(v,r)) return (void)(mx[p]=v);int mid=(l+r)>>1;if (calc(v,mid)>calc(mx[p],mid)) swap(v,mx[p]);if (calc(v,l)>calc(mx[p],l)) modify(ch[p][0],l,mid,v);if (calc(v,r)>calc(mx[p],r)) modify(ch[p][1],mid+1,r,v); } int query(int p,int l,int r,int k) {if (!p) return -INF;int ans=(mx[p]? calc(mx[p],k):-INF);int mid=(l+r)>>1;if (k<=mid) ans=max(ans,query(ch[p][0],l,mid,k));else ans=max(ans,query(ch[p][1],mid+1,r,k));return ans; } void solve(int l,int r) {if (l==r){clear();f[l][1]+=val[l][1];for (int i=1;i<=m;i++){if (i>1) f[l][i]=max(f[l][i],query(rt,1,N,i))+val[l][i];++tot,k[tot]=buf[l][i],b[tot]=f[l][i]-i*k[tot];modify(rt,1,N,tot);}return;}int mid=(l+r)>>1;solve(l,mid);clear();for (int j=1;j<=m;j++){for (int i=l;i<=mid;i++){++tot,k[tot]=buf[i][j],b[tot]=f[i][j]-(i+j)*k[tot];modify(rt,1,N,tot);}for (int i=mid+1;i<=r;i++) f[i][j]=max(f[i][j],query(rt,1,N,i+j));}solve(mid+1,r); } int main() {n=read(),m=read();for (int i=1;i<=n;i++){buf[i].resize(m+1);for (int j=1;j<=m;j++) buf[i][j]=read();}for (int i=1;i<=n;i++){val[i].resize(m+1),f[i].resize(m+1,-INF);for (int j=1;j<=m;j++) val[i][j]=read();}f[1][1]=0;solve(1,n);printf("%d\n",f[n][m]);return 0; }

總結

以上是生活随笔為你收集整理的【牛客NOIP模拟】 牛牛的RPG游戏【二维偏序】【任意坐标斜率优化】【CDQ 分治】【李超线段树】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。