Codeforces Round #321 (Div. 2)【A 最长不减子串】【B tow-pointer】【C dfs】【D 状压DP】

传送门:A. Kefa and First Steps

题意:求最长不递减子串

思路:直接扫一遍就好了~

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+6;
int ans = 0;
int a[maxn];
int res = 0;
int main()
{
     int n;
     scanf("%d",&n);
     for (int i = 1;i<=n;i++)
         scanf("%d",&a[i]);
     for (int i = 2;i<=n;i++)
     {
         if (a[i]>=a[i-1])  {
             res++;
             ans = max(ans,res);
         }
         else  res=0;
     }
     printf("%d\n",ans+1);
}


传送门:B. Kefa and Company

题意:
一个人有n个朋友,他想找他的n个朋友来玩,但是朋友间会相互攀比,就不能带他们的财富差距大于或等于d的,
他的朋友间还有好友度
求来的最大的朋友的友好度good
首先给你两个数n和d,分别代表有n个朋友,然后不超过d,
下面有n行,分别表示朋友的金钱数目和友好度(好有现实写照~)

思路:
先按照钱的多少排一下序,然后双指针暴力寻找最大的好友度
#include <bits/stdc++.h>
#define pr(x) cout << #x << "= " << x << "  "
#define pl(x) cout << #x << "= " << x << endl;
#define Memset(x, a) memset(x, a, sizeof(x))
#define ll __int64
using  namespace  std;
const int inf=0x3f3f3f3f;

pair<ll,ll>a[100010];
ll  n,d;

inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

bool  cmp(pair<ll,ll> a,pair<ll,ll>b){
    return   a.first<b.first;
}

int  main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    n=read();d=read();
    for(int i=0; i<n; i++){
        a[i].first=read();a[i].second=read();
    }
    sort(a,a+n,cmp);
    ll st=0,ed=0,ans=0,sum=0;
    while(ed<n){
        while(a[ed].first-a[st].first<d&&ed<n){
            sum+=a[ed].second;
            ed++;
        }
        ans=max(ans,sum);
        sum-=a[st].second;
        st++;
    }
    cout<<ans<<endl;
    return 0;
}

传送门: C. Kefa and Park
题意: A的家在1,其余没有子节点的点都是餐厅,途中不能经过m次以上的红点(值为1)问他能去几个餐厅?

思路 深搜。需要注意的是他是无向的。
#include <bits/stdc++.h>
using  namespace  std;

int  a[100010];
int  vis[100010];
vector<int>v[100010];
int res=0;
int n,m;

inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

int  dfs(int cur,int res){ //层数 ,当前连续有猫数
    if(a[cur])res++;  //如果有猫,当前连续值+1
    else res=0;   //没猫,连续值置0
    if(res>m||vis[cur])return 0;   //如果连续有猫大于m或者该点被访问过返回0
    vis[cur]=1;
    int  ans=0;
    if(v[cur].size()==1&&cur>1)return 1;  //如果访问到餐厅(没有子节点)
    for(int i=0; i<v[cur].size(); i++){
        ans+=dfs(v[cur][i],res);
    }
    return ans;
}
int  main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    n=read();m=read();
    for(int i=1; i<=n; i++){
        a[i]=read();
    }
    for(int i=0; i<n-1; i++){
        int x,y;
        x=read();y=read();
        v[x].push_back(y);
        v[y].push_back(x);
    }
    cout<<dfs(1,0)<<endl;
    return 0;
}

传送门: D. Kefa and Dishes
题意: 有n种菜,现在选m种菜来吃,还有很多条好处,如果在吃y的前一道菜是x的话,那么就可以获得满意度。每一种菜都有一个满意度。
思路: 裸的状态压缩dp,如果你敢写O(n^2*2^n)复杂度的代码的话,那基本就做完了。设dp[S][i]表示为最后一道菜为i,现在的菜吃的状态为S。S中的二进位如果为1表示已经吃了,如果是0则表示没吃,然后一个记忆化搜索,答案就出了了。
这道题基本就可以测出CF评测机的速度,n=18,O(n^2*2^n)复杂度的记忆化搜索代码跑了405ms,可见CF评测机1000ms跑10^9复杂度很轻松
#include <bits/stdc++.h>
#define Memset(x, a) memset(x, a, sizeof(x))
#define ll __int64
using  namespace  std;
const int inf=0x3f3f3f3f;


int n,m,k;
ll v[20],buf[20][20];//v[]存每道菜满意度,buf[][]存不同顺序的增加满意度
ll dp[1<<19][20];

ll dfs(int S,int u,int p){  //已经访问过的节点集合S,当前位置u
    if(dp[S][u]>=0)return  dp[S][u]; //刚开始写的dp[][]>0结果test29超时,因为题目中ai都可以是0,所以细节啊啊啊~
    if(p==m)return  0;

    ll res=0;
    for(int i=0; i<n; i++){
        if(S&(1<<i))continue;
        res=max(res,dfs(S^(1<<i),i,p+1)+v[i]+buf[u][i] );
    }
    return  dp[S][u]=res;
}

inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

int  main(){
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
    int x,y,val;
    n=read();m=read();k=read();
    for(int i=0; i<n; i++)
        v[i]=read();
    Memset(buf,0);
    while(k--){
        x=read();y=read();val=read();
        buf[x-1][y-1]=val;
    }
    Memset(dp,-1);
    printf("%I64d\n",dfs(0,19,0));
    return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值