不管夜晚多么黑暗,黎明总是会到来。
T1.BRS
最大子段和,线段树维护区间sum,lmx,rmx,mx四个值。
考虑最大子段和只能存在于左区间,右区间,或者跨越两个区间,合并即可。
复杂度O(mlogn)
(活生生看错题)
#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
",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];
}
T3.olddriver
n范围非常小,可以离散化后朴素地标记做。O(n^3)
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
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;
}
const int MAXN=1005;
int orix[MAXN],oriy[MAXN],oriu[MAXN],oriv[MAXN];
int x[MAXN],y[MAXN],u[MAXN],v[MAXN];
vector<int> setx,sety;
int n;
bool mp[MAXN][MAXN];
int main(){
n=rd();
for(int i=1;i<=n;i++){
setx.push_back(orix[i]=rd());
sety.push_back(oriy[i]=rd());
setx.push_back(oriu[i]=rd());
sety.push_back(oriv[i]=rd());
}
sort(setx.begin(),setx.end());
sort(sety.begin(),sety.end());
for(int i=1;i<=n;i++){
x[i]=lower_bound(setx.begin(),setx.end(),orix[i])-setx.begin();
u[i]=lower_bound(setx.begin(),setx.end(),oriu[i])-setx.begin();
y[i]=lower_bound(sety.begin(),sety.end(),oriy[i])-sety.begin();
v[i]=lower_bound(sety.begin(),sety.end(),oriv[i])-sety.begin();
}
for(int i=1;i<=n;i++)
for(int j=x[i];j<u[i];j++)
for(int k=y[i];k<v[i];k++)
mp[j][k]=1;
long long ans=0;
int totx=setx.size(),toty=sety.size();
for(int i=1;i<totx;i++){
for(int j=1;j<toty;j++){
if(!mp[i-1][j-1]) continue;
ans+=(long long)(setx[i]-setx[i-1])*(sety[j]-sety[j-1]);
}
}
cout<<ans;
return 0;
}