首页 > 其他分享 >5.3考试总结

5.3考试总结

时间:2024-05-03 20:11:59浏览次数:24  
标签:总结 5.3 205 int long -- 考试 return dp

今天考的好一些。(244分,rk 2)

T1 [CF1279C] Stack of Presents

显而易见,每次排序的时候肯定是把先取出来的排在前面,所以只需要维护一个指针 \(z\),表示目前最靠里的一个礼物,假如现在这个要取的礼物比它靠外,贡献为 1,否则它之前所有礼物都在它的外侧,计算出贡献后,将 \(z\) 改为这个礼物。

时间复杂度 \(O(t(n+m))\)。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+5;
int t,n,m,a[N],c[N];
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>t;while(t--){
        cin>>n>>m;
        int z=0;ll ans=0;
        for(int i=1;i<=n;i++)
            cin>>a[i],c[a[i]]=i;
        for(int i=1,b;i<=m;i++){
            cin>>b;if(z>c[b]) ans++;
            else ans+=(c[b]-i)*2+1,z=c[b];
        }cout<<ans<<"\n";
    }return 0;
}

T2 [luogu5522]棠梨煎雪

(堂梨煎雪是什么啊?)

明显可以想到拆开每一位分别维护。

发现维护的就是 \(n\) 个单点修改,区间查询的数列,里面可能是 \(0,1,?\)。

容易想到,假如一个区间内部全是 \(?\),那么可能性翻倍;假如一个区间内同时存在 \(0,1\),就没有符合条件的解。

存在性可以用两个树状数组维护,时间复杂度 \(O(nq\log m)\),由于小常数所以能过。

我当时在考场上写的是线段树,时间复杂度一样,但是常数大,所以 \(TLE60\)。

//线段树代码(T)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int M=2e7+5;
int n,m,q,id,rt[35];
int ls[M],rs[M],as[M];
int c[35][100010],ans;
int push_up(int l,int r){
    if(l==4||r==4) return 4;
    if(l==3) return r;
    if(r==3) return l;
    if(l!=r) return 4;
    return l;
}void build(int a,int x,int l,int r){
    if(l==r){
        as[x]=c[a][l];
        return;
    }int mid=(l+r)/2;
    ls[x]=++id;rs[x]=++id;
    build(a,ls[x],l,mid);
    build(a,rs[x],mid+1,r);
    as[x]=push_up(as[ls[x]],as[rs[x]]);
}void change(int x,int l,int r,int w,int t){
    if(l==r){
        as[x]=t;
        return;
    }int mid=(l+r)/2;
    if(w<=mid) change(ls[x],l,mid,w,t);
    else change(rs[x],mid+1,r,w,t);
    as[x]=push_up(as[ls[x]],as[rs[x]]);
}int que(int x,int l,int r,int s,int e){
    if(s<=l&&r<=e) return as[x];
    int mid=(l+r)/2;
    if(s>mid) return que(rs[x],mid+1,r,s,e);
    if(e<=mid) return que(ls[x],l,mid,s,e);
    return push_up(que(ls[x],l,mid,s,e),que(rs[x],mid+1,r,s,e));
}int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n>>m>>q;
    for(int i=1;i<=m;i++){
        string s;
        cin>>s;
        for(int j=0;j<n;j++){
            if(s[j]=='0') c[j+1][i]=1;
            if(s[j]=='1') c[j+1][i]=2;
            if(s[j]=='?') c[j+1][i]=3;
        }
    }for(int i=1;i<=n;i++){
        rt[i]=++id;
        build(i,rt[i],1,m);
    }while(q--){
        int o;cin>>o;
        if(!o){
            int l,r,sum=1;
            cin>>l>>r;
            for(int i=1;i<=n;i++){
                int u=que(rt[i],1,m,l,r);
                if(u==4){sum=0;break;}
                if(u==3) sum*=2;
            }ans^=sum;
            continue;
        }int p;cin>>p;
        string s;
        cin>>s;
        for(int i=0;i<n;i++){
            int chg;
            if(s[i]=='0') chg=1;
            if(s[i]=='1') chg=2;
            if(s[i]=='?') chg=3;
            change(rt[i+1],1,m,p,chg);
        }
    }cout<<ans;
    return 0;
}
//树状数组做法(AC)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,q,id,ans;
int c[35][2][100010];
string s[100010];
void add(int x,int y,int a,int b){
    for(;x<=m;x+=x&-x)
        c[a][b][x]+=y;
}int que(int x,int a,int b){
    int re=0;
    for(;x;x-=x&-x)
        re+=c[a][b][x];
    return re;
}int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n>>m>>q;
    for(int i=1;i<=m;i++){
        cin>>s[i];
        for(int j=0;j<n;j++){
            if(s[i][j]=='0') add(i,1,j+1,0);
            if(s[i][j]=='1') add(i,1,j+1,1);
        }
    }while(q--){
        int o;cin>>o;
        if(!o){
            int l,r,sum=1;
            cin>>l>>r;
            for(int i=1;i<=n;i++){
                int u=que(r,i,0)-que(l-1,i,0);
                int v=que(r,i,1)-que(l-1,i,1);
                if(u&&v){sum=0;break;}
                if(!u&&!v) sum*=2;
            }ans^=sum;
            continue;
        }int p;cin>>p;
        string t;cin>>t;
        for(int i=0;i<n;i++){
            int x=-1,y=-1;
            if(t[i]=='0') x=0;
            if(t[i]=='1') x=1;
            if(s[p][i]=='0') y=0;
            if(s[p][i]=='1') y=1;
            if(y>=0) add(p,-1,i+1,y);
            if(x>=0) add(p,1,i+1,x);
        }s[p]=t;
    }cout<<ans;
    return 0;
}

T3 [luogu1174] 打砖块

容易看出是 \(dp\)。

发现调整打砖块的顺序可能会得到更高分,所以考虑“借子弹”的方法。即打一半不打了,送一颗子弹给别的列,换另外一边打完所有的 \(Y\),然后再把子弹还回来。

考虑设 \(dp_{i,j,0/1}\) 表示在第 \(i\) 列,前面一共用了 \(j\) 枚子弹,是否借子弹。则有:

\[\begin{cases} dp_{i,j,0}=\max(dp_{i-1,j,0},\max\limits_{l=1}^n(dp_{i-1,j-t_{i,l},1}+s1_{i,l},dp_{i-1,j-t_{i,l},0}+s2_{i,l}))\\ dp_{i,j,1}=\max(dp_{i-1,j,1},\max\limits_{l=1}^n(dp_{i-1,j-t_{i,l},1}+s2_{i,l})) \end{cases} \]

\(t_{i,j}\) 表示第 \(i\) 列打到第 \(j\) 个点所用子弹数,\(s1_{i,j}\) 表示第 \(i\) 列打到第 \(j\) 个点的收益,\(s2_{i,j}\) 表示第 \(i\) 列打到第 \(j\) 个点和其后面紧跟的所有 \(Y\) 点的收益。这些都可以通过预处理得到。

时间复杂度 \(O(nmk)\)。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,k,w[205],t[205][205];
int a[205][205],b[205][205];
int s1[205][205],s2[205][205];
int dp[205][205][2],ans,sum;
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n>>m>>k;
    for(int i=n;i;i--)
        for(int j=1;j<=m;j++){
            char c;cin>>a[i][j]>>c;
            if(c=='Y') b[i][j]=1;
            sum+=a[i][j];
        }
    for(int j=1;j<=m;j++)
        for(int i=1;i<=n;i++){
            if(!b[i][j]){
                w[j]=i;
                break;
            }ans+=a[i][j];
        }
    for(int j=1;j<=m;j++)
        for(int i=w[j];i<=n;i++)
            s2[j][i]=s1[j][i]=s1[j][i-1]+a[i][j];
    for(int j=1;j<=m;j++){
        t[j][w[j]]=1;
        for(int i=w[j];i<=n;i++){
            int id=i;while(b[id+1][j]) id++;
            s2[j][i]+=s1[j][id]-s1[j][i];
            t[j][id+1]=t[j][i]+1;i=id;
        }
    }for(int j=0;j<=m;j++)
        dp[j][0][0]=-1e9;
    for(int j=1;j<=m;j++)
        for(int l=1;l<=k;l++){
            dp[j][l][0]=dp[j-1][l][0];
            dp[j][l][1]=dp[j-1][l][1];
            for(int i=w[j];i<=n;i++){
                if(b[i][j]||l<t[j][i]) continue;
                dp[j][l][0]=max(dp[j][l][0],dp[j-1][l-t[j][i]][1]+s1[j][i]);
                dp[j][l][0]=max(dp[j][l][0],dp[j-1][l-t[j][i]][0]+s2[j][i]);
                dp[j][l][1]=max(dp[j][l][1],dp[j-1][l-t[j][i]][1]+s2[j][i]);
            }
        }
    cout<<min(sum,dp[m][k][0]+ans);
    return 0;
}

T4 [NOIP2015] 斗地主(普通版)

大模拟,不多说了,详见代码。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int t,n,ans,s[25];
void dfs(int x){
    if(x>=ans) return;
    //一、顺子
    int k=0;//1.单顺子
    for(int i=3;i<=14;i++){
        if(!s[i]) k=0;
        else k++;
        if(k<5) continue;
        for(int j=i;j>i-k;j--) s[j]--;
        dfs(x+1);
        for(int j=i;j>i-k;j--) s[j]++;
    }k=0;//2.双顺子
    for(int i=3;i<=14;i++){
        if(s[i]<2) k=0;
        else k++;
        if(k<3) continue;
        for(int j=i;j>i-k;j--) s[j]-=2;
        dfs(x+1);
        for(int j=i;j>i-k;j--) s[j]+=2;
    }k=0;//3.三顺子
    for(int i=3;i<=14;i++){
        if(s[i]<3) k=0;
        else k++;
        if(k<2) continue;
        for(int j=i;j>i-k;j--) s[j]-=3;
        dfs(x+1);
        for(int j=i;j>i-k;j--) s[j]+=3;
    }//二、老带新
    //先枚举三张牌/炸弹
    for(int i=2;i<=14;i++){
        if(s[i]<3) continue;
        //1.三带一/二
        s[i]-=3;
        //(1)带单张牌
        for(int j=2;j<=15;j++){
            if(!s[j]||j==i) continue;
            s[j]--;dfs(x+1);s[j]++;
        }//(2)带对子(大小王不是对子)
        for(int j=2;j<=14;j++){
            if(s[j]<2) continue;
            s[j]-=2;dfs(x+1);s[j]+=2;
        }s[i]+=3;
        if(s[i]<4) continue;
        //2.四带二
        s[i]-=4;
        //(1)带俩单张牌
        for(int j=2;j<=15;j++){
            //枚举第一张牌
            if(!s[j]) continue;
            for(int l=2;l<=15;l++){
                //枚举第二张牌
                if(!s[l]||l==j) continue;
                s[j]--;s[l]--;
                dfs(x+1);
                s[j]++;s[l]++;
            }
        }//(2)带俩对子
        for(int j=2;j<=14;j++){
            //枚举第一个对子
            if(s[j]<2) continue;
            for(int l=2;l<=14;l++){
                //枚举第二个对子
                if(s[l]<2||l==j) continue;
                s[j]-=2;s[l]-=2;
                dfs(x+1);
                s[j]+=2;s[l]+=2;
            }
        }s[i]+=4;
    }//三、就地解决
    for(int i=2;i<=15;i++)
        if(s[i]) x++;
    ans=min(ans,x);
}int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>t>>n;
    while(t--){
        memset(s,0,sizeof(s));
        for(int i=1;i<=n;i++){
            int x,y;
            cin>>x>>y;
            if(!x) x=15;
            if(x==1) x=14;
            s[x]++;
        }ans=25;dfs(0);
        cout<<ans<<"\n";
    }return 0;
}

标签:总结,5.3,205,int,long,--,考试,return,dp
From: https://www.cnblogs.com/chang-an-22-lyh/p/18171553/2024-5-3_ks

相关文章

  • 中考常见同义词和同义短语总结
    about(大约)=orsoacoupleof=several=afewa(large)numberof=manyalittle=alittlebitalotof=lotsof=many/muchapieceofadvice=asuggestionaquartertofive=fourforty-fiveateacherwithexperience=anexperiencedteachera......
  • 5.3
    有人懂吗众部,随我行军!......
  • 5.3 居家养老web端控制台
    基于vue3+ElementPlus做的一个居家养老静态界面,内容准备后期实现以下是效果图特别声明用到了百度地图JSAPI进行位置展示与iVCam模拟实时监控 以下是代码部分<scriptsetup>import{onMounted,onBeforeUnmount}from'vue'import{ref}from'vue'constvideoRef......
  • 2024.5.3【比赛】高一下三调
    为了拓宽自己的英雄池,还是要写一下。分数&排名:理想:会牵挂的叫亲人,回不去的是故乡。现实:神虎一跃,威震天地!A.李时珍的皮肤衣今天输了,明天也要卷土重来。赛后加点卡赛时是不理解的。为啥这次就加点,上次数据范围错了都不把数据范围错的删了给我重测。自己手动模......
  • 操作系统总结
    首先,我们从概念说起,操作系统是一种系统软件,它是计算机硬件和其他软件之间的桥梁。它的作用便是管理和控制计算机的硬件资源,如处理器、内存、硬盘等等,操作系统的主要任务又包括进程管理、内存管理、文件系统管理、设备管理和网络管理等。操作系统的发展是从微机操作系统到多处理器......
  • 微机结构总结
    通过对微机结构的学习,我对微机有了更加全面的了解。微机,又称为“微型计算机”,是相对于大型计算机而言的。它以微处理器为核心,配合内存、输入输出接口电路和相应的辅助电路而构成的裸机。下面是他的结构组成:中央处理器(CPU):CPU是微机的核心部件,它负责执行程序中的指令,完成各种算术......
  • 操作系统总结
    操作系统的地位:操作系统是计算机硬件上加载的第一层软件,是对计算机硬件功能的首次扩充。其他软件只有在操作系统的支持下,才能对计算机硬件工作。操作系统是一种重要的系统软件。计算机硬件加上I/O管理软件称为虚拟机,虚拟机再加上文件管理软件称为较强的虚拟机,较强的虚拟机再加上......
  • 《操作系统》分析与总结
    通过这段时间对《操作系统》的学习,我有了很多感受,首先操作系统是计算机系统中最基本的系统软件之一。操作系统的主要功能包括进程管理、内存管理、文件系统管理和设备管理。现代操作系统已经具备了强大的功能和稳定性,为计算机用户提供了便利的操作环境。首先,操作系统中有内存管理......
  • 操作系统总结
    计应232朱思嘉,发表操作系统总结操作系统有两大特点,硬件相关,应用无关。操作系统包含进程。进程概念是一个具有一定独立功能程序在一个数据集合上的一次动态执行过程,进程的特点有,动态性,独立性,并发性,结构性。进程由程序+数据+PCB构成(标志性)。引入线程是将进程间的多个程序执行流并发......
  • 初中中考英语词汇大全003掌握常用词汇,轻松应对考试
    PDF格式公众号回复关键字:ZKCH0031ancient古代的;古老的modern现代的;时髦的official官方的;正式的;公务员foreign外国的;外来的2soonerorlater迟早;早晚有一天allthetime一直;始终overandover一遍又一遍;反复地inahurry匆忙地;立即;很快地3slower更慢......