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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【NOI2019】弹跳【二维线段树】【dijkstra】

發(fā)布時間:2023/12/3 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【NOI2019】弹跳【二维线段树】【dijkstra】 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題意:一個w×hw\times hw×h的二維平面上有nnn個城市,有mmm個彈跳裝置,第iii個可以花費tit_iti?的時間從城市pip_ipi?跳到矩形x∈[l,r],y∈[u,d]x\in [l,r],y\in[u,d]x[l,r],y[u,d]中的任意一個城市。求從111到其他每個城市的最小時間。

w,h≤n≤7×104,m≤1.5×105w,h\leq n\leq7\times 10^4,m\leq1.5\times10^5w,hn7×104,m1.5×105 空間限制128M

考慮直接套dijkstra的思路,每次選出dis最小的點,松弛它可以到的點,然后把它刪掉。

挪到二維平面上,你需要支持:

  • 全局詢問最小值
  • 矩形取min?\minmin
  • 刪除一個點
  • 用kdt或者二維線段樹維護即可。這里用的是二維線段樹。

    需要注意的細(xì)節(jié):

  • 要動態(tài)開點
  • 要用pair記錄最小值的編號,且初值是(INF,INF),否則可能打了個lazy標(biāo)記之后first是答案標(biāo)號卻是0。
  • 大常數(shù)選手需要維護一個最大值剪枝。
  • #include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <vector> #include <utility> #define re register #define MAXN 70005 using namespace std; const int INF=0x7fffffff; inline int read() {int ans=0;char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans; } typedef pair<int,int> pi; #define mp make_pair #define fi first #define se second struct tran{int xl,xr,yl,yr;tran(int xl=0,int xr=0,int yl=0,int yr=0):xl(xl),xr(xr),yl(yl),yr(yr){}}; inline bool belong(const tran& b,const tran& a){return a.xl<=b.xl&&b.xr<=a.xr&&a.yl<=b.yl&&b.yr<=a.yr;} inline bool ninter(const tran& a,const tran& b){return (a.xr<b.xl||b.xr<a.xl)||(a.yr<b.yl||b.yr<a.yl);} struct edge{tran t;int w;}; vector<edge> e[MAXN]; #define ch(x) t[p].son[x] int tot=0,rt; struct node{tran pos;pi mn;int mx,sum,lzy,son[4];}t[MAXN<<5]; inline int newnode(int xl,int xr,int yl,int yr) {int p=++tot;t[p].pos=tran(xl,xr,yl,yr);t[p].mn=mp(INF,INF);t[p].mx=0;t[p].lzy=INF;return p; } inline void update(int p) {t[p].sum=t[ch(0)].sum+t[ch(1)].sum+t[ch(2)].sum+t[ch(3)].sum;t[p].mn=mp(INF,INF),t[p].mx=0;for (re int i=0;i<4;++i) if (ch(i)) t[p].mn=min(t[p].mn,t[ch(i)].mn),t[p].mx=max(t[p].mx,t[ch(i)].mx); } inline void pushlzy(int p,int v) {if (t[p].sum==0) return;t[p].mn.fi=min(t[p].mn.fi,v),t[p].mx=min(t[p].mx,v),t[p].lzy=min(t[p].lzy,v); } inline void pushdown(int p) {if (t[p].lzy<INF){for (re int i=0;i<4;++i) pushlzy(ch(i),t[p].lzy);t[p].lzy=INF;} } void modify(int& p,int xl,int xr,int yl,int yr,int x,int y,int v) {if (!p) p=newnode(xl,xr,yl,yr);if (!belong(tran(x,x,y,y),t[p].pos)) return;pushdown(p);if (t[p].pos.xl==t[p].pos.xr&&t[p].pos.yl==t[p].pos.yr) return (void)(t[p].sum=(v<INF),t[p].mn=mp(INF,v),t[p].mx=(v==INF? 0:INF));int xmid=(xl+xr)>>1,ymid=(yl+yr)>>1; modify(ch(0),xl,xmid,yl,ymid,x,y,v);modify(ch(1),xl,xmid,ymid+1,yr,x,y,v);modify(ch(2),xmid+1,xr,yl,ymid,x,y,v);modify(ch(3),xmid+1,xr,ymid+1,yr,x,y,v); update(p); } void modify(int p,tran q,int v) {if (!p) return;pushdown(p); if (t[p].mx<=v) return;if (belong(t[p].pos,q)) return pushlzy(p,v);if (ninter(t[p].pos,q)) return;for (int i=0;i<4;i++) modify(ch(i),q,v);update(p); } int x[MAXN],y[MAXN],ans[MAXN]; int main() {int n,m,w,h;n=read(),m=read(),w=read(),h=read();for (int i=1;i<=n;i++){x[i]=read(),y[i]=read();modify(rt,1,w,1,h,x[i],y[i],i);}for (int i=1;i<=m;i++){int p,t,l,r,d,u;p=read(),t=read(),l=read(),r=read(),d=read(),u=read();e[p].push_back((edge){tran(l,r,d,u),t});}modify(1,tran(x[1],x[1],y[1],y[1]),0);for (int T=1;T<=n;T++){pi tmp=t[1].mn;int u=tmp.se,dis=tmp.fi;ans[u]=dis;for (int i=0;i<(int)e[u].size();i++)modify(1,e[u][i].t,dis+e[u][i].w);modify(rt,1,w,1,h,x[u],y[u],INF);}for (int i=2;i<=n;i++) printf("%d\n",ans[i]);return 0; }

    總結(jié)

    以上是生活随笔為你收集整理的【NOI2019】弹跳【二维线段树】【dijkstra】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。