luogu P6772 [NOI2020] 美食家
阿新 • • 發佈:2021-07-25
題面傳送門
這麼小的\(n\),這麼大的\(T\)肯定是矩陣快速冪的節奏。
我們考慮這個邊的時間怎麼處理。
因為時間是真的小,所以我們可以將每個點拆成\(5\)個點,然後由每個點的第\(w\)個點向那邊的點連邊。
然後這個美食節我們可以拆成\(k+1\)段,每一段直接矩陣快速冪,中間乘上特殊矩陣。
然後我們發現這個東西是\(O(k(5n)^3logT)\)的過不去。
我們只要\(A_{1,1}\),所以可以參照那道NOI online只儲存第一行的那個向量然後每次向量和矩陣相乘就少一個\(5n\)
預處理2的冪次矩陣就變成了\(O((5n)^3logT+k(5n)^2logT)\)
code:
#include<bits/stdc++.h> #define I inline #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define abs(x) ((x)>0?(x):-(x)) #define re register #define ll long long #define db double #define N 250 #define M 200000 #define mod 998244353 #define eps (1e-5) #define U unsigned int #define it iterator #define Gc() getchar() #define Me(x,y) memset(x,y,sizeof(x)) using namespace std; int n,m,k,T,x,y,z,W[N+5]; struct matrix{ ll A[N+5][N+5]; matrix(){Me(A,-0x3f);} matrix operator *(const matrix &B)const{ matrix C;re int i,j,h;for(i=1;i<=5*n;i++){ for(j=1;j<=5*n;j++){ for(h=1;h<=5*n;h++) C.A[i][j]=max(C.A[i][j],A[i][h]+B.A[h][j]); } }return C; } }bas[40],G; struct vecto{ ll A[N+5]; vecto(){Me(A,-0x3f);} vecto operator *(const matrix &B)const{ vecto C;re int i,j;for(i=1;i<=5*n;i++){ for(j=1;j<=5*n;j++) C.A[i]=max(C.A[i],A[j]+B.A[j][i]); }return C; } }Ans; struct ques{int T,x,y;}S[N+5];I bool cmp(ques x,ques y){return x.T<y.T;} int main(){ freopen("1.in","r",stdin); re int i,j;scanf("%d%d%d%d",&n,&m,&T,&k);for(i=1;i<=n;i++) scanf("%d",&W[i]);for(i=1;i<=m;i++) scanf("%d%d%d",&x,&y,&z),G.A[(x-1)*5+z][(y-1)*5+1]=W[y]; for(i=1;i<=n;i++) for(j=5*(i-1)+1;j<5*i;j++)G.A[j][j+1]=0; bas[0]=G;for(i=1;i<=30;i++)bas[i]=bas[i-1]*bas[i-1]; for(i=1;i<=k;i++)scanf("%d%d%d",&S[i].T,&S[i].x,&S[i].y);sort(S+1,S+k+1,cmp);Ans.A[1]=W[1]; for(i=1;i<=k;i++){ x=S[i].T-S[i-1].T-1;for(j=30;~j;j--) (x>>j)&1&&(Ans=Ans*bas[j],0);for(j=1;j<=5*n;j++) G.A[j][5*(S[i].x-1)+1]+=S[i].y;Ans=Ans*G;for(j=1;j<=5*n;j++) G.A[j][5*(S[i].x-1)+1]-=S[i].y; }x=T-S[k].T;for(i=30;~i;i--) (x>>i)&1&&(Ans=Ans*bas[i],0); /*for(i=1;i<=x;i++) Ans=Ans*G;*/ printf("%lld\n",(Ans.A[1]>=0)?Ans.A[1]:-1); }