不管夜晚多么黑暗,黎明总是会到来。
T1.BRS
最大子段和,线段树维护区间sum,lmx,rmx,mx四个值。
考虑最大子段和只能存在于左区间,右区间,或者跨越两个区间,合并即可。
(活生生看错题)
#include<iostream> #include<cstdio> using namespace std; const int MAXN=524288; inline int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } #define ls (cur<<1) #define rs (cur<<1|1) #define mid (l+r>>1) struct Node{ Node(int x=0){sum=lmx=rmx=mx=x;} int sum,lmx,rmx,mx; }node[MAXN<<2]; int a[MAXN]; void pushup(int cur){ node[cur].sum=node[ls].sum+node[rs].sum; node[cur].lmx=max(node[ls].lmx,node[ls].sum+node[rs].lmx); node[cur].rmx=max(node[rs].rmx,node[rs].sum+node[ls].rmx); node[cur].mx=max(node[ls].rmx+node[rs].lmx,max(node[ls].mx,node[rs].mx)); } void build(int cur,int l,int r){ if(l==r) {node[cur]=Node(a[l]);return;} build(ls,l,mid);build(rs,mid+1,r); pushup(cur); } void update(int x,int cur,int l,int r,int w){ if(l==r) {node[cur]=Node(w);return;} if(x<=mid) update(x,ls,l,mid,w); else update(x,rs,mid+1,r,w); pushup(cur); } Node query(int L,int R,int cur,int l,int r){ if(L<=l&&r<=R) return node[cur]; Node lnode,rnode,ret; if(L<=mid) lnode=query(L,R,ls,l,mid); if(mid <R) rnode=query(L,R,rs,mid+1,r); if(!(L<=mid)) return rnode; if(!(mid <R)) return lnode; ret.sum=lnode.sum+rnode.sum; ret.lmx=max(lnode.lmx,lnode.sum+rnode.lmx); ret.rmx=max(rnode.rmx,rnode.sum+lnode.rmx); ret.mx=max(lnode.rmx+rnode.lmx,max(lnode.mx,rnode.mx)); return ret; } int n,m; int main(){ n=rd();m=rd(); for(int i=1;i<=n;i++) a[i]=rd(); build(1,1,n); int q,x,y; for(int i=1;i<=m;i++){ q=rd();x=rd();y=rd(); if(q==1) printf("%d\n",query(x,y,1,1,n).mx); else update(x,1,1,n,y); } return 0; }
T2.fyfy
上台阶问题升级版,一次上k阶,总数巨大。
对于一次上k阶,定义f(x)为走到第x阶的方案,显然有f(x)=Σf(i),其中x-k+1<=i<=x-1,且i>=0
初值f(0)=f(1)=1,注意到k非常小(k<=10),可以开一个矩阵,类比fib数列,就完了。
复杂度O(logn*k^3)
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int n,m; const int MOD=7777777; struct Mat{ int siz; long long a[16][16]; Mat(int x=10){memset(a,0,sizeof(a));siz=x;} Mat operator*(const Mat &rhs){ Mat ret(m); for(int k=0;k<=m;k++){ for(int i=0;i<=m;i++){ for(int j=0;j<=m;j++){ (ret.a[i][j]+=(1ll*a[i][k]*rhs.a[k][j])%MOD)%=MOD; } } } return ret; } }e; Mat qpow(const Mat &x,int y){ Mat ret=e,base=x; while(y){ if(y&1) ret=ret*base; base=base*base; y>>=1; } return ret; } int ans[16]; int main(){ cin>>m>>n; e.siz=m; Mat cur(m); for(int i=0;i<=m;i++) e.a[i][i]=1ll; for(int i=0;i<=m-1;i++){ cur.a[i+1][i]=1ll; } for(int i=1;i<=m;i++) cur.a[i][m]=1ll; Mat ori(m); ori.a[0][0]=1ll;ori.a[0][1]=1ll; cur=qpow(cur,n+1); Mat fn(m); fn=ori*cur; cout<<fn.a[0][m]; }