zoukankan      html  css  js  c++  java
  • csps模拟93序列,二叉搜索树,走路题解

    题面:

    模拟93考得并不理想,二维偏序没看出来,然而看出来了也不会打

    序列:

    对a,b数列求前缀和,那么题意转化为了满足$suma[i]>=suma[j]$且$sumb[i]>=sumb[j]$的最大$i-j+1$值

    那么就是二维偏序,那么按a排序,把b塞到树状数组里

     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
    ",ans);
    70     return 0;
    71 }
    View Code

    二叉搜索树:

    区间dp,设f[i,j]表示考虑区间[i,j]的贡献,则f[i,j]=min(f[i,k-1]+f[k+1,j]+a[i,j])

    然后发现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
    ",f[1][n]);
    44     return 0;
    45 }
    View Code

    走路:分治消元

     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
    ",ans[i]);
    76     return 0;
    77 }
    View Code
  • 相关阅读:
    菜鸟涂鸦作品展_No.29
    菜鸟涂鸦作品展_No.27
    菜鸟涂鸦作品展_No.26
    关注的前沿动态
    货币转换
    第二周总结
    老鼠
    71 打印沙漏
    学习总结0.0
    第五周作业
  • 原文地址:https://www.cnblogs.com/Juve/p/11767396.html
Copyright © 2011-2022 走看看