題面:node
模擬93考得並不理想,二維偏序沒看出來,然而看出來了也不會打ios
序列:數組
對a,b數列求前綴和,那麼題意轉化爲了知足$suma[i]>=suma[j]$且$sumb[i]>=sumb[j]$的最大$i-j+1$值ide
那麼就是二維偏序,那麼按a排序,把b塞到樹狀數組裏spa
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<cstdlib> 7 #include<ctime> 8 #define int long long 9 using namespace std; 10 const int MAXN=5e5+5; 11 int n,ans=0,sta[MAXN],top=0; 12 int read(){ 13 int x=0,f=1;char ch=getchar(); 14 while(ch<'0'||ch>'9'){ 15 if(ch=='-') f=-1; 16 ch=getchar(); 17 } 18 while(ch>='0'&&ch<='9'){ 19 x=(x<<3)+(x<<1)+ch-'0'; 20 ch=getchar(); 21 } 22 return x*f; 23 } 24 struct node{ 25 int a,b,id; 26 friend bool operator < (node p,node q){ 27 return p.a==q.a?p.b<q.b:p.a<q.a; 28 } 29 }val[MAXN]; 30 int lowbit(int x){ 31 return x&-x; 32 } 33 int c[MAXN]; 34 void update(int pos,int val){ 35 for(int i=pos;i<=top;i+=lowbit(i)){ 36 c[i]=min(c[i],val); 37 } 38 } 39 int query(int pos){ 40 int res=0x3f3f3f3f3f3f3f3f; 41 for(int i=pos;i>0;i-=lowbit(i)){ 42 res=min(res,c[i]); 43 } 44 return res; 45 } 46 signed main(){ 47 n=read(); 48 for(int i=1;i<=n;++i){ 49 val[i].a=read(); 50 val[i].a+=val[i-1].a; 51 val[i].id=i; 52 } 53 for(int i=1;i<=n;++i){ 54 val[i].b=read(); 55 val[i].b+=val[i-1].b; 56 sta[++top]=val[i].b; 57 } 58 sort(val+1,val+n+1); 59 sort(sta+1,sta+top+1); 60 top=unique(sta+1,sta+top+1)-sta-1; 61 for(int i=1;i<=n;++i) 62 val[i].b=lower_bound(sta+1,sta+top+1,val[i].b)-sta; 63 memset(c,0x3f,sizeof(c)); 64 for(int i=1;i<=n;++i){ 65 int res=query(val[i].b); 66 ans=max(ans,val[i].id-res); 67 update(val[i].b,val[i].id); 68 } 69 printf("%lld\n",ans); 70 return 0; 71 }
二叉搜索樹:code
區間dp,設f[i,j]表示考慮區間[i,j]的貢獻,則f[i,j]=min(f[i,k-1]+f[k+1,j]+a[i,j])blog
而後發現k有決策單調性,因此咱們記錄一個dp數組,dp[i,j]表示f[i,j]是由那一個k轉移而來,而後對於每個i,j,枚舉k的範圍就變成了dp[i+1,j]到dp[i,j-1]排序
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #define int long long 7 using namespace std; 8 const int MAXN=5005; 9 int n,ans=0,sum[MAXN],f[MAXN][MAXN],dp[MAXN][MAXN]; 10 struct node{ 11 int x,id; 12 friend bool operator < (node p,node q){ 13 return p.x==q.x?p.id>q.id:p.x>q.x; 14 } 15 }a[MAXN]; 16 int min(int p,int q){ 17 return p<q?p:q; 18 } 19 signed main(){ 20 memset(f,0x3f,sizeof(f)); 21 scanf("%lld",&n); 22 for(int i=1;i<=n;++i){ 23 scanf("%lld",&a[i].x); 24 a[i].id=i; 25 sum[i]=sum[i-1]+a[i].x; 26 f[i][i]=a[i].x; 27 dp[i][i]=i; 28 } 29 for(int i=0;i<=n+1;++i){ 30 for(int j=0;j<i;++j) f[i][j]=0; 31 } 32 for(int l=2;l<=n;++l){ 33 for(int i=1;i+l-1<=n;++i){ 34 int j=i+l-1; 35 for(int k=dp[i][j-1];k<=dp[i+1][j];++k){ 36 if(f[i][j]>=f[i][k-1]+f[k+1][j]+sum[j]-sum[i-1]){ 37 f[i][j]=f[i][k-1]+f[k+1][j]+sum[j]-sum[i-1]; 38 dp[i][j]=k; 39 } 40 } 41 } 42 } 43 printf("%lld\n",f[1][n]); 44 return 0; 45 }
走路:分治消元get
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define int long long 6 using namespace std; 7 const int MAXM=1e5+5,mod=998244353; 8 int n,m,du[305],cnt[305][305],inv[MAXM],a[305][305],ans[305]; 9 int q_pow(int a,int b,int p){ 10 int res=1; 11 while(b){ 12 if(b&1) res=res*a%p; 13 a=a*a%p; 14 b>>=1; 15 } 16 return res; 17 } 18 void solve(int l,int r){ 19 if(l==r){ 20 ans[l]=(a[1][n+1]+mod)%mod; 21 return ; 22 } 23 int t[305][305]; 24 for(int i=1;i<=n;++i){ 25 for(int j=1;j<=n+1;++j) 26 t[i][j]=a[i][j]; 27 } 28 int mid=(l+r)>>1; 29 for(int x=mid+1;x<=r;++x){ 30 int invv=q_pow(a[x][x],mod-2,mod); 31 for(int i=1;i<=n+1;++i) (a[x][i]*=invv)%=mod; 32 for(int i=1;i<=n;++i){ 33 if(i==x) continue; 34 invv=a[i][x]; 35 for(int j=l;j<=r;++j){ 36 a[i][j]=(a[i][j]-a[x][j]*invv+mod)%mod; 37 } 38 a[i][n+1]=(a[i][n+1]-a[x][n+1]*invv+mod)%mod; 39 } 40 } 41 solve(l,mid); 42 for(int i=1;i<=n;++i){ 43 for(int j=1;j<=n+1;++j) 44 a[i][j]=t[i][j]; 45 } 46 for(int x=l;x<=mid;++x){ 47 int invv=q_pow(a[x][x],mod-2,mod); 48 for(int i=1;i<=n+1;++i) (a[x][i]*=invv)%=mod; 49 for(int i=1;i<=n;++i){ 50 if(i==x) continue; 51 invv=a[i][x]; 52 for(int j=l;j<=r;++j){ 53 a[i][j]=(a[i][j]-a[x][j]*invv%mod+mod)%mod; 54 } 55 a[i][n+1]=(a[i][n+1]-a[x][n+1]*invv%mod+mod)%mod; 56 } 57 } 58 solve(mid+1,r); 59 } 60 signed main(){ 61 scanf("%lld%lld",&n,&m); 62 for(int i=1,u,v;i<=m;++i){ 63 scanf("%lld%lld",&u,&v); 64 ++du[u],++cnt[u][v]; 65 } 66 for(int i=1;i<=m;++i) inv[i]=q_pow(i,mod-2,mod); 67 for(int i=1;i<=n;++i){ 68 for(int j=1;j<=n;++j){ 69 a[i][j]=cnt[i][j]*q_pow(du[i],mod-2,mod)%mod; 70 } 71 a[i][n+1]=-1; 72 --a[i][i]; 73 } 74 solve(1,n); 75 for(int i=2;i<=n;++i) printf("%lld\n",ans[i]); 76 return 0; 77 }