• cf自训4.10


    cf933A dp题

    一开始看错是连续子序列了,然后样例刚好能过。。

    然后正解没想出来,网上看了题解:感觉正解是枚举2开始的位置,然后再枚举翻转的区间,pos左右两侧分别求出贡献最大的那个区间,左右两部分的贡献是独立计算的

    #include <cstdio>
    #include <cmath>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define mst(a,b) memset((a),(b),sizeof(a))
    #define rush() int T;scanf("%d",&T);while(T--)
     
    typedef long long ll;
    const int maxn = 2005;
    const ll mod = 1e9+7;
    const ll INF = 1e18+5;
    const double eps = 1e-9;
     
    int n;
    int a[maxn];
    int pre1[maxn];
    int pre2[maxn];
     
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            pre1[i]=pre1[i-1]+(a[i]==1);
        }
        for(int i=n;i>=1;i--) pre2[i]=pre2[i+1]+(a[i]==2);
        int ans=0;
        for(int k=1;k<=n+1;k++)                   //枚举位置pos
        {
            int num1=0,num2=0;
            for(int i=1;i<=k;i++) num1=max(num1,pre1[i-1]+pre2[i]-pre2[k]);   //枚举l
            for(int i=k;i<=n+1;i++) num2=max(num2,pre2[i]+pre1[i-1]-pre1[k-1]);  //枚举r
            ans=max(ans,num1+num2);
        }
        printf("%d
    ",ans);
    }
    View Code

    然后是神仙做法,因为答案必定是11111222221111122222的前缀样式,所以只要从左到右扫一次即可。。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define maxn 2000
    
    int n;
    int a[maxn+5];
    int f[maxn+5][5];
    
    int main() {
        scanf("%d",&n);
        for(int i=1; i<=n; i++) scanf("%d",&a[i]);
        for(int i=1; i<=n; i++) {
            for(int j=1; j<=4; j++) {
                f[i][j]=f[i][j-1];
                if(a[i]==(j+1)%2+1) f[i][j]=max(f[i][j],f[i-1][j]+1);
                else f[i][j]=max(f[i][j],f[i-1][j]);
            }
        }
        printf("%d",f[n][4]);
        return 0;
    }
    View Code

    cf938D 最短路+新建源点

    第一次在cf上做这种题,这题就是把每个点权转化为到源点的边权,然后跑一次最短路即可

    /*
    给定无向图,有边权和点权
    现在要求出每个点i的最小代价2*d(i,j)+aj,i可以等于j 
    建图:边权*2,建立源点和每个点连边,边权是ai
    然后以源点为起点跑最短路即可 
    */
    #include<bits/stdc++.h>
    #include<queue>
    using namespace std;
    #define maxn 400005
    #define ll long long
    struct Edge{ll to,nxt,w;}edge[maxn<<2]; 
    ll head[maxn],tot,n,m,a[maxn];
    void init(){
        memset(head,-1,sizeof head);
        tot=0;
    }
    void addedge(ll u,ll v,ll w){
        edge[tot].to=v;edge[tot].w=w;
        edge[tot].nxt=head[u];head[u]=tot++;
    }
    
    ll d[maxn],v[maxn];
    priority_queue<pair<ll,ll> >pq;
    void dijkstra(){
        memset(d,0x3f,sizeof d);
        memset(v,0,sizeof v);
        d[n+1]=0;
        pq.push(make_pair(0,n+1));
        while(pq.size()){
            pair<ll,ll>c=pq.top();pq.pop();
            if(v[c.second])continue;
            v[c.second]=1;
            ll x=c.second;
            for(int i=head[x];i!=-1;i=edge[i].nxt){
                ll y=edge[i].to,w=edge[i].w;
                if(v[y])continue;
                if(d[y]>d[x]+w){
                    d[y]=d[x]+w;
                    pq.push(make_pair(-d[y],y));
                }
            }
        }
    }
    
    
    int main(){
        init();
        cin>>n>>m;
        for(int i=1;i<=m;i++){
            ll u,v,w;
            cin>>u>>v>>w;
            addedge(u,v,2*w);
            addedge(v,u,2*w); 
        }
        for(int i=1;i<=n;i++){
            cin>>a[i];
            addedge(i,n+1,a[i]);
            addedge(n+1,i,a[i]);
        }
        dijkstra();
        
        for(int i=1;i<=n;i++)
            cout<<d[i]<<" ";    
    } 
    View Code

    cf939E 三分+简单公式

    学了下三分的写法,能用来求单峰函数的极值

    三分链接: https://blog.csdn.net/pi9nc/article/details/9666627 

    /*
    1.往多重集合s里加数 ,每次给的数时单调不递减的 
    2.求子集ss,使max(ss)-mean(ss)最大 
    三分法来做即可 
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 500005
    #define ll long long
    double sum[maxn],n;
    ll len,Max;
    double f(int i){
        return ((double)sum[i]+Max)/(i+1);
    }
    double sanfen(int l,int r){
        while(l<r-1){
            int mid=(l+r)>>1;
            int mmid=(mid+r)>>1;
            if(f(mid)>f(mmid))
                l=mid;
            else r=mmid;
        }
        if(f(l)>f(r))return f(r);
        return f(l);
    }
    int main(){
        int q,op;
        cin>>q;
        while(q--){
            cin>>op;
            if(op==1){
                cin>>Max;
                sum[++len]=Max+sum[len-1];        
            }
            else {
                printf("%.10lf
    ",Max-sanfen(1,len-1));
            }
        }    
    } 
    View Code

    cf935D 概率递推dp

    还是第一次做这种题。。要学一下概率dp了。。

    /*
    概率递推+逆元取模运算
    从末尾往前推比从前往后推要更简单 
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long 
    #define mod 1000000007
    #define maxn 100005
    ll a[maxn],b[maxn],n,m,dp[maxn];
    ll inv2,invm;
    ll exgcd(ll a,ll b,ll &x,ll &y){
        if(b==0){x=1,y=0;return a;}
        ll d=exgcd(b,a%b,x,y);
        ll z=x;x=y;y=z-a/b*x;
        return d;
    }
    
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=n;i++)cin>>b[i];
        ll x,y;
        exgcd(2,mod,x,y);inv2=(x+mod)%mod;
        exgcd(m,mod,x,y);invm=(x+mod)%mod;
        for(int i=n;i>=1;i--){
            if(a[i] && b[i]){//第i位都是固定的数 
                if(a[i]==b[i])dp[i]=dp[i+1];
                else dp[i]=a[i]>b[i];
            }
            else if(b[i])//ai填数,ai==bi的概率+ai>bi的概率 
                dp[i]=dp[i+1]*invm%mod+(m-b[i])*invm%mod; 
            else if(a[i])//bi填数,ai==bi的概率+ai>bi的概率 
                dp[i]=dp[i+1]*invm%mod+(a[i]-1)*invm%mod; 
            else if(!a[i] && !b[i])//都填数,ai==bi的概率+ai!=bi且ai>bi的概率 
                dp[i]=dp[i+1]*invm%mod+(m-1)*inv2%mod*invm%mod;
        }
        cout<<dp[1]%mod<<endl;
    } 
    View Code
  • 相关阅读:
    重新整理 .net core 实践篇————防跨站脚本攻击[四十]
    重新整理 .net core 实践篇————重定向攻击[三十九]
    低数值精度推理和训练
    FinFET与芯片制程
    LLVM Backend技术
    安霸Ambarella CV系列芯片
    3D卷积,代码实现
    TVM darknet yolov3算子优化与量化代码的配置方法
    英特尔 QLC 3D NAND 数据存储
    Graph Representation 图神经网络
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10686768.html
Copyright © 2020-2023  润新知