我的隔天Codeforces——Round #372 (Div. 2)

首先说下这场比赛我不是隔天过的,当时是我参赛的。很可惜只过了三题,第四题实在是想不出来。而且过三题的速度十分之慢,还没有学弟快,一个是因为我的读题速度实在是感人,还有我的写法一般也是十分之恶心。唉,真TM丢人。



A. Crazy Computer

分析:给你n个数,求最后有多少个连续且相邻两个数之间的差值不超过c的个数。一开始我以为是很简单的题目,照着题意模拟即可。卧槽,写这篇题解的时候想到了,模拟个p,直接从最后搜索找到连续个差值小于c的个数就直接输出了。我正着写的话,还要维护一个值,还难写。

int main(){
    //freopen("d:\\acm\\in.in","r",stdin);
    int n,c;
    scanf("%d %d",&n,&c);
    int a=-1,b;
    int ans;
    for(int i=0;i<n;i++){
        if(a<0){
            scanf("%d",&a);
            ans=1;
        }
        else {
            scanf("%d",&b);
            if(b-a<=c){
                ans++;
                //cout<<ans<<endl;
                a=b;
            }
            else {
                ans=1;
                a=b;
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}


B. Complete the Word

分析:给你一个字符串,只包含大写字母和?,?表示能和任何大写字母匹配(能够变成任何大写字母)。问给你的字符串能不能变成,存在至少一个长度为26的子串正好包含所有26个字母的字符串,如果能输出某一个这样的字符串,不能就输出-1。题目稍微有点复杂,但是思路还是比较好想的。其实就是先特判一下前26个字符(总长度如果小于26,直接-1)有没有可能成为那种子串(统计一下这26个字符中每个大写字母出现的次数,如果有出现大于等于2次的,那么显然是不能称为这种子串的,如果都不超过1的话就是可能的),不能就依次向下搜索,加上下一个字符的信息,删去最开始的字符的信息。还有,不要忘记将其他?随便一个字符。

char dat[maxn];
int num[30];
void buquan(int n){
    for(int i=0;i<n;i++)
        if(dat[i]=='?')
            dat[i]='A';
}
int main(){
    //freopen("d:\\acm\\in.in","r",stdin);
    scanf("%s",dat);
    int len=strlen(dat);
    int cnt=0;
    if(len<26){
        puts("-1");
        return 0;
    }
    for(int i=0;i<26;i++)
        if(dat[i]!='?'){
            num[dat[i]-'A']++;
            if(num[dat[i]-'A']==2)cnt++;
        }
    if(!cnt){
        int k=0;
        for(int i=0;i<26;i++)
            if(dat[i]=='?'){
                while(num[k])
                    k++;
                num[k]=1;
                dat[i]='A'+k;
            }
        buquan(len);
        printf("%s\n",dat);
        return 0;
    }
    for(int i=26;i<len;i++){
        if(dat[i-26]!='?'){
            num[dat[i-26]-'A']--;
            if(num[dat[i-26]-'A']==1)cnt--;
        }
        if(dat[i]!='?'){
            num[dat[i]-'A']++;
            if(num[dat[i]-'A']==2)cnt++;
        }
        if(!cnt){
            int k=0;
            for(int j=i-25;j<=i;j++)
                if(dat[j]=='?'){
                    while(num[k])
                        k++;
                    num[k]=1;
                    dat[j]='A'+k;
                }
            buquan(len);
            printf("%s\n",dat);
            return 0;
        }
    }
    puts("-1");
    return 0;
}


C. Plus and Square Root

分析:这看起来是道难题,但是其实是一道找规律题。按照数字最小的原则(因为好算,而且统一起来就有规律了,题目没有要求),对于i,其实是要开根号得到 i(i1) ,1的时候特判一下。那么就的到公式 (i(i+1))2i(i1)i=i3+2i2+1 ,那么只要循环输出即可,1的时候要特判。你问我这道想法,就是找规律,你写出了前几项找找就行了。

int main(){
    //freopen("d:\\acm\\in.in","r",stdin);
    int n;
    scanf("%d",&n);
    puts("2");
    for(int i=2;i<=n;i++){
        printf("%lld\n",1ll*i*i*i+2ll*i*i+1);
    }
    return 0;
}


D. Complete The Graph

分析:给你一个有向图G(n,m),没有重边。你需要给定某些边的权值,使得s和t之间的最短路正好等于L。这是一道比较难的图论题,比赛的时候没有做出来,但是看完别人的代码恍然大悟,原来这么做。我们首先不妨将这些没有定义边权的边的边权都赋为最小的1 ,先跑一遍最短路,如果此时s和t都不能连通或者最短路大于L的话,那么不会有任何其他方法使得最短路变得更小,除非边权小于等于0;如果正好等于L的情况,那么正好输出;但是麻烦就是麻烦在小于L的情况,需要多次调试边权得到答案。这样看的话,这道题目更像一道构造题,感觉这么想的话,给我的启发又深了一层。我们遍历所有开始的时候没有边权的边,对于每一条边加上现在s和t之间的最短路与L之间的差值,然后重新跑一遍最短路,看一下s和t之间的最短路是否是L,如果不是的话,那么更新这个差值,对于下一条开始没有边权的边进行新一轮的操作。不过扫一遍还不能使得最短路等于L的话,说明其中最短路是由开始时有边权的边组成的。我感觉这做法是正确的,但是你要我证明那我还真的不会。但是我觉得这种方法不应该只用于这道题,好多其他构造题目都可以使用,学到一招。

#include <map>
#include <set>
#include <ctime>
#include <stack>
#include <cmath>
#include <queue>
#include <bitset>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <fstream>
#include <cstdlib>
#include <sstream>
#include <cstring>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:1024000000,1024000000")

using namespace std;
#define   maxn          10000+10
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   clr(x,y)      memset(x,y,sizeof(x))
#define   rep(i,n)      for(int i=0;i<(n);i++)
#define   repf(i,a,b)   for(int i=(a);i<=(b);i++)
#define   pii           pair<int,int>
#define   mp            make_pair
#define   FI            first
#define   SE            second
#define   IT            iterator
#define   PB            push_back
#define   Times         10

typedef   long long     ll;
typedef   unsigned long long ull;
typedef   long double   ld;

const double eps   = 1e-10;
const double  pi   = acos(-1.0);
const  ll    mod   = 1e9+7;
const  int   inf   = 0x3f3f3f3f;
const  ll    INF   = (ll)1e18+300;
const double delta = 0.98;

inline void RI(int& x)
{
    x=0;
    char c=getchar();
    while(!((c>='0'&&c<='9')||c=='-'))c=getchar();
    bool flag=1;
    if(c=='-')
    {
        flag=0;
    }
    while(c<='9'&&c>='0')
    {
        x=x*10+c-'0';
        c=getchar();
    }
    if(!flag)x=-x;
}

//--------------------------------------------------

struct edge{
    int u,v;
    ll w;
    int next;
}dat[maxn<<1];
int n,m,edgenum;
int head[maxn];
int mark[maxn];
bool vis[maxn];
ll dis[maxn];
void add_edge(int u,int v,ll w){
    dat[edgenum].u=u;
    dat[edgenum].v=v;
    dat[edgenum].w=w;
    dat[edgenum].next=head[u];
    head[u]=edgenum++;
}
void spfa(int s){
    queue<int>q;
    for(int i=0;i<n;i++){
        vis[i]=false;
        dis[i]=inf;
    }
    dis[s]=0;
    vis[s]=true;
    q.push(s);
    while(!q.empty()){
        int x=q.front();
        q.pop();
        vis[x]=false;
        for(int i=head[x];i!=-1;i=dat[i].next){
            int y=dat[i].v;
            ll xy=dat[i].w;
            if(dis[x]+xy<dis[y]){
                dis[y]=dis[x]+xy;
                if(!vis[y]){
                    vis[y]=true;
                    q.push(y);
                }
            }
        }
    }
}
void print(){
    puts("YES");
    for(int i=0;i<m;i++)
        printf("%d %d %lld\n",dat[i*2].u,dat[i*2].v,dat[i*2].w);
}
int main(){
    //freopen("d:\\acm\\in.in","r",stdin);
    ll L;
    int x,y;
    scanf("%d %d %lld %d %d",&n,&m,&L,&x,&y);
    edgenum=0;
    clr(head,-1);
    for(int i=0;i<m;i++){
        int u,v;
        ll w;
        scanf("%d %d %lld",&u,&v,&w);
        if(w==0){
            w=1;
            mark[i]=1;
        }
        add_edge(u,v,w);
        add_edge(v,u,w);
    }
    spfa(x);
    if(dis[y]==inf||dis[y]>L)puts("NO");
    else if(dis[y]==L)print();
    else {
        ll tmp=L-dis[y];
        for(int i=0;i<m;i++)
            if(mark[i]){
                dat[i*2].w+=tmp;
                dat[i*2+1].w+=tmp;
                spfa(x);
                tmp=L-dis[y];
                if(tmp==0){
                    print();
                    return 0;
                }
            }
        puts("NO");
    }
    return 0;
}


继续努力,争取以后四题上紫。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值