20191029+

前言

  • 发现现在连搜索都不会打了……T2可以搜索的。
  • 期望题一旦卡精度我一般都会爆零啊。
  • 还是要自己推柿子。

T1

  • 先处理出两个前缀和数组$a_i,b_i$。
  • 问题转换成了点对$(a_i,b_i,w_i)$的三维偏序问题。
  • 然而并不会CDQ,所以将点对按$a_i$排序,然后用线段树或树状数组维护就行了。
  • 时间复杂度$Theta(NlogN)$,空间复杂度$Theta(N)$。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define getchar() ((S==T&&(T=(S=buf)+fread(buf,1,L,stdin),S==T))?EOF:*S++)
int const N=5e5+5,L=1<<20|1;
int n,ans,tot;
char buf[L],*S,*T;
ll a[N],b[N];
struct Pair{
    ll fir;
    int sec;
    Pair(){}
    Pair(ll x,int y):fir(x),sec(y){}
}s[N];
struct node{
    ll fr;
    int sc,id;
}c[N];
int BIT[N];
inline int read(){
    int ss(0),pp(1);char bb(getchar());
    for(;bb<48||bb>57;bb=getchar())if(bb=='-')pp=-1;
    while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
    return ss*pp;
}
inline int _min(int x,int y){
    return x<y?x:y;
}
inline int _max(int x,int y){
    return x>y?x:y;
}
inline int ask(int x){
    int as=N;
    while(x)as=_min(as,BIT[x]),x-=x&-x;
    return as;
}
inline void add(int x,int y){
    while(x<=tot)BIT[x]=_min(y,BIT[x]),x+=x&-x;
    return ;
}
int main(){
    //freopen("sequence.in","r",stdin);
    //freopen("1.out","w",stdout);
    n=read();
    for(register int i=1;i<=n;++i)a[i]=a[i-1]+read();
    for(register int i=1;i<=n;++i){
        s[i]=Pair(b[i]=b[i-1]+read(),i);
        if(a[i]>=0&&b[i]>=0)ans=i;
    }
    std::sort(s+1,s+n+1,[](Pair skyh,Pair yxs){
        return skyh.fir<yxs.fir;
    });
    s[0].fir=s[1].fir-1;
    for(register int i=1;i<=n;++i)
        b[s[i].sec]=tot=tot+(s[i].fir!=s[i-1].fir);
    for(register int i=1;i<=n;++i)
        c[i].fr=a[i],c[i].sc=b[i],c[i].id=i;
    std::sort(c+1,c+n+1,[](node skyh,node yxs){
        return (skyh.fr^yxs.fr)?skyh.fr<yxs.fr:skyh.sc<yxs.sc;
    });
    memset(BIT,0x3f,tot+1<<2);
    for(register int i=1;i<=n;++i)
        ans=_max(ans,c[i].id-ask(c[i].sc)),add(c[i].sc,c[i].id);
    printf("%d",ans);
    return 0;
}
View Code

T2

  • 暴力DP其实很好想到的,但考试的时候没有想到枚举根节点。
  • 决策单调性可以感性理解一下?然后就可以通过了。
  • 时空复杂度$Theta(N^2)$。
#include<cstdio>
#define ll long long
using namespace std;
int const N=5005;
ll const lar=1e18;
int n;
int a[N],s[N][N];
ll w[N],dp[N][N];
inline ll _min(ll x,ll y){
    return x<y?x:y;
}
int main(){
    scanf("%d",&n);
    for(register int i=1;i<=n;++i){
        scanf("%lld",&dp[i][i]),w[i]=w[i-1]+dp[i][i];
        s[i][i]=i;s[i+1][i]=0;
    }
    s[1][0]=1;
    for(register int i=2;i<=n;++i)
        for(register int j=1,lt=n-i+1,u;j<=lt;++j){
            dp[j][u=j+i-1]=lar;
            ll wnow=w[u]-w[u-i];
            for(register int k=s[j][u-1],lit=s[j+1][u];k<=lit;++k){
                ll z=dp[j][k-1]+dp[k+1][u]+wnow;
                if(dp[j][u]>z)s[j][u]=k,dp[j][u]=z;
            }
        }
    printf("%lld",dp[1][n]);
    return 0;
}
View Code

T3

  • 将柿子推出来后不难想到暴力。
  • 发现每次高斯消元的对象变化很小。
  • 于是采用分治消元。
#include<cstdio>
#include<cstring>
#include<vector>
#define ll long long
#define getchar() ((S==T&&(T=(S=buf)+fread(buf,1,L,stdin),S==T))?EOF:*S++)
using namespace std;
int const N=302,M=1e5+5,L=1<<20|1,mod=998244353;
int n,m,lt;
char buf[L],*S,*T;
int head[N],Next[M],du[N],to[M],t;
int a[11][N][N];
inline int read(){
    int ss(0);char bb(getchar());
    while(bb<48||bb>57) bb=getchar();
    while(bb>=48&&bb<=57) ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
    return ss;
}
inline void add(int y,int x){
    to[++t]=y,++du[x];
    Next[t]=head[x],head[x]=t;
    return ;
}
inline ll power(ll x,int y=mod-2,ll as=1){
    for(;y;y>>=1,x=x*x%mod)
        if(y&1) as=as*x%mod;
    return as;
}
inline int up(int x){
    return x<0?x+mod:x;
}
void MergeGauss(int l,int r,int k){
    if(l==r){
        if(l^1)printf("%d
",up(a[k-1][1][n]));
        return ;
    }
    int mid=l+r>>1;
    memcpy(a[k],a[k-1],sizeof(a[k]));
    for(register int i=mid+1;i<=r;++i){
        ll x=power(a[k][i][i]);
        for(register int j=1;j<=n;++j)a[k][i][j]=x*a[k][i][j]%mod;
        for(register int j=1;j<n;++j){
            if(j==i)continue;
            ll z=a[k][j][i];
            for(register int u=l;u<=r;++u)a[k][j][u]=(-z*a[k][i][u]+a[k][j][u])%mod;
            a[k][j][n]=(-z*a[k][i][n]+a[k][j][n])%mod;
        }
    }
    MergeGauss(l,mid,k+1);
    memcpy(a[k],a[k-1],sizeof(a[k]));
    for(register int i=l;i<=mid;++i){
        ll x=power(a[k][i][i]);
        for(register int j=1;j<=n;++j)a[k][i][j]=x*a[k][i][j]%mod;
        for(register int j=1;j<n;++j){
            if(j==i)continue;
            ll z=a[k][j][i];
            for(register int u=l;u<=r;++u)a[k][j][u]=(-z*a[k][i][u]+a[k][j][u])%mod;
            a[k][j][n]=(-z*a[k][i][n]+a[k][j][n])%mod;
        }
    }
    MergeGauss(mid+1,r,k+1);
    return ;
}
int main(){
    n=read()+1,m=read();
    for(register int i=1,ff;i<=m;++i) add(read(),read());
    for(register int i=1,inow;i<n;++i){
        inow=power(du[i]);
        a[0][i][i]=a[0][i][n]=1;
        for(register int j=head[i];j;j=Next[j])
            a[0][i][to[j]]=up(a[0][i][to[j]]-inow);
    }
    return MergeGauss(1,n-1,1),0;
}
View Code
原文地址:https://www.cnblogs.com/remarkable/p/11769084.html