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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

LuoguP5897 [IOI2013]wombats

發(fā)布時間:2023/12/3 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LuoguP5897 [IOI2013]wombats 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

LuoguP5897 [IOI2013]wombats

題目描述

簡要題意:有一個R?CR*CR?C的網(wǎng)格圖,邊有邊權,支持修改,多次詢問V1,V2V_1,V_2V1?,V2?,求點(0,V1)(0,V_1)(0,V1?)(R?1,V2)(R-1,V_2)(R?1,V2?)的最短路(只能往左右和往下走)。

Solution

f[i][j]f[i][j]f[i][j]表示從(0,i)(0,i)(0,i)(0,j)(0,j)(0,j)的最短路,可以通過一行一行DPDPDPO(R?C2)O(R*C^2)O(R?C2)的時間內求得,而每次修改需要重新求答案,所以時間復雜度為O(R?C2?Q)O(R*C^2*Q)O(R?C2?Q)

但我們發(fā)現(xiàn)這題的RRR很大,而CCC很小,所以我們考慮把RRR這一位扔到線段樹上,線段樹的一個區(qū)間記錄了一個C?CC*CC?C的矩陣。線段[l,r][l,r][l,r]中矩陣的一個點Di,jD_{i,j}Di,j?記錄從(l,i)(l,i)(l,i)(r,j)(r,j)(r,j)的距離,這樣每次修改就只需要修改lognlog^nlogn

接下來考慮兩個線段怎么合并,如果暴力枚舉的話時間復雜度為O(n3)O(n^3)O(n3)(類似floydfloydfloyd的方法,枚舉i,ji,ji,j和中間點kkk),但我們發(fā)現(xiàn)這里有決策單調性,我們固定一個點iii,枚舉jjj,假設jjj的最優(yōu)決策點為kkk,那么對于任意的j′>jj'>jj>jj′j'j的最優(yōu)決策點k′>kk'>kk>k,這樣就可以通過分治做到O(n2lgn)O(n^2lgn)O(n2lgn)或直接記錄決策點位置做到O(n2)O(n^2)O(n2)

這樣優(yōu)化之后時間復雜度就OKOKOK了。然而空間還是太大了,于是有一個神奇的套路:在線段樹中,若線段的長度小于一個閾值ttt,則通過之前說的O(n3)O(n^3)O(n3)暴力求解DDD矩陣。

我的程序當閾值設為20的時候能過。
所以時空復雜度就是O(能過)O(能過)O()了(懶得算QAQ)

#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <ctime> #include <cassert> #include <string.h> //#include <unordered_set> //#include <unordered_map> //#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B) #define PB(A) push_back(A) #define SIZE(A) ((int)A.size()) #define LEN(A) ((int)A.length()) #define FOR(i,a,b) for(int i=(a);i<(b);++i) #define fi first #define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; } template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll; typedef unsigned long long ull; typedef long double lod; typedef pair<int,int> PR; typedef vector<int> VI;const lod eps=1e-11; const lod pi=acos(-1); const int oo=1<<30; const ll loo=1ll<<62; const int mods=998244353; const int MAXN=5005; const int INF=0x3f3f3f3f;//1061109567 /*--------------------------------------------------------------------*/ inline int read() {int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f; } int n,m,d1[MAXN][205],d2[MAXN][205],s[MAXN][205],tmp[205][205]; struct Matrix {int A[205][205],l,r;void clear(int L,int R) {l=L,r=R;for (int i=1;i<=m;i++) for (int j=1;j<=m;j++) A[i][j]=INF;}Matrix(int L=0,int R=0) { clear(L,R); }void rebuild(int L,int R){l=L,r=R;for (int i=1;i<=m;i++) for (int j=1;j<=m;j++) A[i][j]=abs(s[l][i]-s[l][j]);for (int k=l+1;k<=r;k++){for (int i=1;i<=m;i++)for (int j=1;j<=m;j++) A[i][j]+=d2[k][j],tmp[i][j]=A[i][j];for (int i=1,smin;i<=m;i++){smin=tmp[i][1];for (int j=2;j<=m;j++) smin+=d1[k][j],upmin(smin,tmp[i][j]),upmin(A[i][j],smin);smin=tmp[i][m];for (int j=m-1;j>=1;j--) smin+=d1[k][j+1],upmin(smin,tmp[i][j]),upmin(A[i][j],smin);}}}void print(){cout<<l<<" "<<r<<endl;for (int i=1;i<=m;i++){for (int j=1;j<=m;j++) cout<<A[i][j]<<" ";cout<<endl;}cout<<endl;} } ans; struct Segment_Tree {Matrix tree[1005];void Solve(Matrix &x,Matrix &y,int t,int l,int r,int L,int R){ int mid=(l+r)>>1,k=L;for (int i=L+1;i<=R;i++)if (x.A[t][i]+d2[y.l][i]+y.A[i][mid]<x.A[t][k]+d2[y.l][k]+y.A[k][mid]) k=i;ans.A[t][mid]=x.A[t][k]+d2[y.l][k]+y.A[k][mid];if (l==r) return;Solve(x,y,t,l,mid,L,k);Solve(x,y,t,mid+1,r,k,R);}Matrix Merge(Matrix &x,Matrix &y){ ans.clear(x.l,y.r);for (int i=1;i<=m;i++) Solve(x,y,i,1,m,1,m);return ans;}void up(int x) { tree[x]=Merge(tree[x<<1],tree[x<<1|1]); }void build(int x,int l,int r){if (r-l<=20) { tree[x].rebuild(l,r); return; }int mid=(l+r)>>1;build(x<<1,l,mid);build(x<<1|1,mid+1,r);up(x);}void change(int x,int l,int r,int y){if (r-l<=20) { tree[x].rebuild(l,r); return; }int mid=(l+r)>>1;if (y<=mid) change(x<<1,l,mid,y);else change(x<<1|1,mid+1,r,y);up(x);} } segment;int main() {n=read(),m=read();for (int i=1;i<=n;i++)for (int j=2;j<=m;j++) d1[i][j]=read(),s[i][j]=s[i][j-1]+d1[i][j];for (int i=2;i<=n;i++)for (int j=1;j<=m;j++) d2[i][j]=read();segment.build(1,1,n);int Case=read();while (Case--){int opt=read();if (opt==1) { int x=read()+1,y=read()+2;d1[x][y]=read(); for (;y<=m;y++) s[x][y]=s[x][y-1]+d1[x][y];segment.change(1,1,n,x);}else if (opt==2) {int x=read()+2,y=read()+1;d2[x][y]=read(),segment.change(1,1,n,x);}else printf("%d\n",segment.tree[1].A[read()+1][read()+1]);}return 0; }

總結

以上是生活随笔為你收集整理的LuoguP5897 [IOI2013]wombats的全部內容,希望文章能夠幫你解決所遇到的問題。

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