7.20模拟赛

不管夜晚多么黑暗,黎明总是会到来。


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\n",query(x,y,1,1,n).mx);
        else update(x,1,1,n,y);
    }
    return 0;
}
View Code

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];
}
View Code

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;
}
View Code

 

posted @ 2018-07-20 16:16  GhostCai  阅读(109)  评论(0编辑  收藏  举报