9/30-10/1

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了9/30-10/1相关的知识,希望对你有一定的参考价值。

接下来的2个月的方向:
1.每周两场的ICPC区域赛vp,赛后补题,看情况尽量补
2.洛谷上近几年来的省选题,从绿到蓝到紫,一路刷上去
3.多思考,不追求题目的数量,质量才是关键。
4.触类旁通,碰到一个题不会做,一定要去搜寻多个同类型的题目。
5.手速不是拿牌的关键。
6.剩下的就是努力,抓紧时间,有耐力得走完这两个月。


I Steadily Growing Steam

参考了大佬的博客。
感觉这个状态的设计很常规,但为什么自己就像不到呢。
在题意上需要注意一个点:
在玩游戏之前,选出一个序列,数量不大于k,将他们t[i]变成之前的2倍,要求在玩游戏的多次回合中两堆牌点数相同,要求价值最大。

做的时候看出是个背包,配合队友应该能写出来的。
分析:
滚动数组的使用。只涉及前一个状态,可借用&判别奇偶,利用^取上一个状态。
前i张牌 最多使用j次技能 两个牌堆差值为k时获得的最大价值是多少
不选这张牌 f[i][j][k]=f[i-1][j][k]
选入放入a堆 f[x][j][k]=max(f[x][j][k],f[x^1][j][k+t[i]]+v[i])
选入放入b堆 f[x][j][k]=max(f[x][j][k],f[x^1][j][k-t[i]]+v[i])
选入加倍后放入a堆
f[x][j][k]=max(f[x][j][k],f[x^1][j-1][k+2*t[i]]+v[i])
选入加背后放入b堆
f[x][j][k]=max(f[x][j][k],f[x^1][j-1][k-2*t[i]]+v[i])

#include <bits/stdc++.h>
#define int long long
#define endl '\\n'
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int inf=1e18;
const int N=7e5+5;
int n,m,f[2][105][5205],v[105],t[105];
//前i张牌 最多使用j次技能 两个牌堆差值为k时获得的最大价值是多少
//不选这张牌  f[i][j][k]=f[i-1][j][k]
//选入放入a堆 f[i][j][k]=f[i][j][k+a[i]]+v[i]
//选入放入b堆 f[i][j][k]=f[i][j][k-a[i]]+v[i]
void solve()

    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>v[i]>>t[i];
    for(int i=0;i<=m;i++)
        for(int j=0;j<=5200;j++) f[0][i][j]=f[1][i][j]=-inf;
    for(int i=0;i<=m;i++)
        for(int j=0;j<=5200;j++) f[0][i][2600]=0;
    for(int i=1;i<=n;i++)     //多张牌
    
        for(int j=0;j<=m;j++) //加倍次数
        
            for(int k=0;k<=5200;k++)
            
                int x=i&1;
                f[x][j][k]=f[x^1][j][k];
                if(k+t[i]<=5200)
                    f[x][j][k]=max(f[x][j][k],f[x^1][j][k+t[i]]+v[i]);
                if(k>=t[i])
                    f[x][j][k]=max(f[x][j][k],f[x^1][j][k-t[i]]+v[i]);
                if(!j) continue;
                if(k+2*t[i]<=5200)
                    f[x][j][k]=max(f[x][j][k],f[x^1][j-1][k+2*t[i]]+v[i]);
                if(k>=2*t[i])
                    f[x][j][k]=max(f[x][j][k],f[x^1][j-1][k-2*t[i]]+v[i]);
            
        
    
    cout<<f[n&1][m][2600]<<endl;

signed main()

    //ios;
    //int T;cin>>T;
    //while(T--)
        solve();
    return 0;


上海网赛 J - Stone game

两个难想得思维点。
1.虽然说每个石头都面临选和不选两个情况,但是要从那个公式想到01背包还是有点思维量的。
2.第二个难点在于排序,要想到从大到小排序。因为第i块石头若取完后,重量若满足条件,则可以累加上答案dp[j-a[i]]的方案数。

#include <bits/stdc++.h>
#define int long long
#define endl '\\n'
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int inf=1e18;
const int N=7e5+5;
const int mod=1e9+7;
int n,m,dp[N],a[N],ans;
bool cmp(int a,int b)return a>b;
void solve()

    memset(dp,0,sizeof dp);
    ans=0;
    cin>>n;
    int g=0;
    for(int i=1;i<=n;i++) cin>>a[i],g+=a[i];
    sort(a+1,a+n+1,cmp);
    dp[0]=1;
    for(int i=1;i<=n;i++)
    
        for(int j=g;j>=a[i];j--)
        
            dp[j]=(dp[j]+dp[j-a[i]])%mod;
            if(j>=g-j&&j-a[i]<=g-j)
                ans=(ans+dp[j-a[i]])%mod;
        
    
    cout<<ans<<endl;

signed main()

    //ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;


P5329 [SNOI2019]字符串

思路:几个操作需要实现。
根据样例便可以看出:
1.若一个字符大于前一个字符,则将这一段下标放到数组尾部;
2.若一个字符小于前一个字符,则前其放到数组的前端尾部。

#include <bits/stdc++.h>
#define int long long
#define endl '\\n'
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int inf=1e18;
const int N=7e6+5;
const int mod=1e9+7;
bool cmp(int a,int b)return a>b;
int n,a[N];
string s;
void solve()

    cin>>n>>s;
    s=" "+s;
    int l=0,r=n+1,g=1;
    for(int i=2;i<=n;i++)
    
        if(s[i]==s[i-1]) continue;
        if(s[i]>s[i-1])
        
            for(int j=i-1;j>=g;j--)
                a[--r]=j;
            g=i;
        
        else
        
            for(int j=g;j<=i-1;j++)
                a[++l]=j;
            g=i;
        
    
    //cout<<g<<endl;
    for(int i=g;i<=n;i++) a[++l]=i;
    for(int i=1;i<=n;i++)
        cout<<a[i]<<" ";
    cout<<endl;

signed main()

    //ios;
    //int T;cin>>T;
    //while(T--)
        solve();
    return 0;


C. Insertion Sort

四种情况讨论分析,也可打表直接找规律。

#include <bits/stdc++.h>
#define int long long
#define endl '\\n'
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int inf=1e18;
const int N=7e6+5;
const int mod=1e9+7;
bool cmp(int a,int b)return a>b;
int n,k,q;

signed main()

    //ios;
    int tt=0;
    int T;cin>>T;
    while(T--)
    
        cin>>n>>k>>q;
        int ans=1;
        if(n<=k)
        
            for(int i=1;i<=n;i++) ans=ans*i%q;  //第一种情况
            cout<<"Case #"<<++tt<<": "<<ans<<endl;continue;
        
        for(int i=1;i<=k;i++) ans=ans*i%q;  
        ans=ans*((n-k)*(n-1)+1)%q;
        cout<<"Case #"<<++tt<<": "<<ans<<endl;
    
    return 0;


J. How Much Memory Your Code Is Using?

模拟题。接受一行数据后,要注意接受换行符。

#include <bits/stdc++.h>
#define int long long
#define endl '\\n'
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int inf=1e18;
const int N=7e6+5;
const int mod=1e9+7;
bool cmp(int a,int b)return a>b;
int n,g;
char c[105];
void solve()

    g++;
    cin>>n;
    getchar();
    int ans=0;
    for(int i=1;i<=n;i++)
    
        string s;
        getline(cin,s);
        if(s.substr(0,4)=="bool"||s.substr(0,4)=="char")
        
            string ss="";
            int flag=0;
            for(int j=5;j<s.length();j++)
            
                if(s[j]=='[') flag=1;
                if(s[j]>='0'&&s[j]<='9'&&flag) ss+=s[j];
            
            if(ss=="")
                ans+=1;
            else
                ans+=stoi(ss);
        
        else if(s.substr(0,3)=="int"||s.substr(0,5)=="float")
        
            string ss="";
            int flag=0;
            for(int j=5;j<s.length();j++)
            
                if(s[j]=='[') flag=1;
                if(s[j]>='0'&&s[j]<='9'&&flag) ss+=s[j];
            
            if(ss=="")
                ans+=4;
            else
                ans+=4*stoi(ss);
        
        else if(s.substr(0,6)=="double"||s.substr(0,9)=="long long")
        
            string ss="";
            int flag=0;
            for(int j=5;j<s.length();j++)
            
                if(s[j]=='[') flag=1;
                if(s[j]>='0'&&s[j]<='9'&&flag) ss+=s[j];
            
            if(ss=="")
                ans+=8;
            else
                ans+=8*stoi以上是关于9/30-10/1的主要内容,如果未能解决你的问题,请参考以下文章

区间合并一些小思路

白灼秋葵

MySQL: 18 优化后的LRU链表中尾部的缓存页淘汰刷入磁盘的机制

归并排序

用栈实现队列

232. 用栈实现队列