NOIP 模拟 机房欢乐WAK赛

没错,这渣题,考了60分,确实该好好反思自己了,这就是noip难度的题,现在想想觉得很害怕


这里写图片描述

题目:

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述


题解:

hao

显然就是一道暴力模拟…我用的指针写,每次暴力strcpy就可以了

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int MAXN=10000;
char str1[MAXN],str2[MAXN];
void del(char *loc){
    char *l=loc-1,*r=loc+1;
    while(l>=str1&&*l==*loc)l--;
    while(*r==*loc)r++;
    if(r-l-1>=3){
        strcpy(l+1,r);
        del(l+1);
    }
}
int main(){
    freopen("hao.in","r",stdin);
    freopen("hao.out","w",stdout);
    gets(str1);
    int n;
    scanf("%d",&n);
    for(register int i=1;i<=n;i++){
        int loc;char temp;
        scanf("%d %c",&loc,&temp);
        strcpy(str2,str1+loc);
        str1[loc]=temp;
        strcpy(str1+loc+1,str2),del(str1+loc);
        if(*str1) puts(str1);
        else puts("-"); 
    }
    return 0;
}

这个故事告诉我们,暴力地用函数(for的1/4时间的str函数),或许有时候可以直接过,原来我写的链表如下,显然要冗杂很多

#include<cstdio>
#include<iostream>
#include<cstring>

char a[3000+3000],col;
struct Point{
    int val,tail_qian,tail_hou;
}p[3000+3000],s,t;
int loc,value,tail,n;
void insert(int tail,int loc,int value){
    if(s.tail_hou==-2&&t.tail_qian==-1){
        p[tail].tail_qian=-1;
        p[tail].tail_hou=-2;
        s.tail_hou=tail;
        t.tail_qian=tail;
        p[tail].val=value;
        printf("%c\n",value+'A');
        return;
    }
    if(p[loc].tail_qian==-1&&p[loc].tail_hou!=-2){
        s.tail_hou=tail;
        p[tail].tail_qian=-1;
        p[tail].val=value;
        p[tail].tail_hou=loc;
        p[p[tail].tail_hou].tail_qian=tail;
    }else if(p[loc].tail_hou==-2&&p[loc].tail_qian!=-1){
        t.tail_qian=tail;
        p[tail].tail_hou=-2;
        p[tail].val=value;
        p[tail].tail_qian=p[loc].tail_qian;
        p[loc].tail_qian=tail;
    }else if(p[loc].tail_qian==-1&&p[loc].tail_hou==-2){
        s.tail_hou=tail;
        p[tail].tail_qian=-1;
        p[tail].tail_hou=loc;
        p[loc].tail_qian=tail;
        p[tail].val=value;
    }else if(p[loc].tail_qian!=-1&&p[loc].tail_hou!=-2){
        p[tail].tail_qian=p[loc].tail_qian;
        p[tail].tail_hou=loc;
        p[p[tail].tail_qian].tail_hou=tail;
        p[p[tail].tail_hou].tail_qian=tail;
        p[tail].val=value;
    }
    int from=tail,to=tail;
    int valuetemp=value;
    int cntt=1;
    while(true){
        while(p[from].tail_qian!=-1&&p[p[from].tail_qian].val==valuetemp){
            from=p[from].tail_qian;
            cntt++;
        }
        while(p[to].tail_hou!=-2&&p[p[to].tail_hou].val==valuetemp){
            to=p[to].tail_hou;
            cntt++;
        }
        if(cntt<3) break;
        from=p[from].tail_qian;to=p[to].tail_hou;
        if(from==-1&&to==-2){
            s.tail_hou=-2;
            t.tail_qian=-1;
            printf("-\n");return;
        }
        if(from==-1){
            p[to].tail_qian=-1;
            s.tail_hou=to;
        }
        if(to==-2){
            p[from].tail_hou=-2;
            t.tail_qian=from;
        }
        if(from!=-1&&to!=-2){
            p[from].tail_hou=to;
            p[to].tail_qian=from;
        }
        if(p[from].val!=p[to].val) break;
        valuetemp=p[from].val;
        cntt=2;
    }
    int now=s.tail_hou;
    while(now!=-2){
        printf("%c",'A'+p[now].val);
        now=p[now].tail_hou;
    }
    printf("\n");
}
int main(){
    freopen("hao.in","r",stdin);
    freopen("hao.out","w",stdout);
    scanf("%s",a);
    int lena=strlen(a);tail=lena-1;
    p[0].tail_hou=1;p[0].tail_qian=-1;p[0].val=a[0]-'A';
    s.tail_hou=0;
    t.tail_qian=lena-1;
    for(register int i=1;i<lena-1;i++){
        p[i].tail_hou=i+1;
        p[i].tail_qian=i-1;
        p[i].val=a[i]-'A';  
    }
    p[lena-1].tail_hou=-2;
    p[lena-1].tail_qian=lena-2;
    p[lena-1].val=a[lena-1]-'A';
    scanf("%d",&n);
    for(register int i=1;i<=n;i++){
        char tt;
        scanf("%d%c%c",&loc,&tt,&col);
        value=col-'A';
        loc++;
        int now=s.tail_hou,cnt=1;
        while(p[now].tail_hou!=-2){
            if(cnt==loc) break;
            cnt++;
            now=p[now].tail_hou;
        }
        tail++;
        insert(tail,now,value);
    }
}

kun

这道题…显然也是贪心水题,但是坑点很多啊,首先要判空,然后思路是先pop大的,再pop小的,然而实际上还可能要pop已经在栈里的…而且即使直接pop没进栈的,instack也要打成true

#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
stack<int>stk;
int n,now;
bool instack[2000000+10];
int main(){
    freopen("kun.in","r",stdin);
    freopen("kun.out","w",stdout);
    scanf("%d",&n);
    int ned=n;
    for(register int i=1;i<=n;i++){
        scanf("%d",&now);
        if(now==ned){
            printf("%d ",now);
            ned--; instack[now]=true;
            while(instack[ned])ned--;
            while(!stk.empty()&&stk.top()>ned)printf("%d ", stk.top()), stk.pop();  
        }
        else{
            instack[now]=true;
            stk.push(now);
        }
    }
    while(!stk.empty()){
        int temp=stk.top();
        printf("%d ",temp);
        stk.pop();
    }
    return 0;
}
/*
15
6 7 14 9 15 1 4 5 8 3 13 12 10 2 11
*/

nan

这道题一看题目就难到了
显然这道题是找规律…然而我是找不出规律的,所以我们分块来看…把数据按照一定的规律分块,记录每个块的起始数字和终止数字,记录块的数字总数前缀和,再二分一下就可以很快得出答案了,而这个块具体是怎么搞得呢,观察下面的图

这里写图片描述

稍微模拟出这样的一个数列,我们发现一个很神奇的事情就是每个数字的个数竟然又是这样的一个数列,现在我们进行分块,从原数列中的2衍生出来的分一块,3衍生出来的分一块,大概是这么个操作
这里写图片描述
然后我们进一步分块

这里写图片描述

震惊地发现,最后红线分出来的块之中含有的第一行元素的个数,竟然变成了1 * 1 | 2 * 2 + 2 * 3 | 3 * 4 + 3 * 5 |…
等等,这样分出来的块含的元素个数,不就是等差数列可以求的嘛,所以看代码吧

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
const long long MAXN=2000000+10;
const long long lk=1e9+7;
int n,t;
long long f[MAXN],last[MAXN],len,l,r,cnt;
struct Block{long long from,to;}block[MAXN];
int main(){
    freopen("nan.in","r",stdin);
    freopen("nan.out","w",stdout);
    last[1]=1;last[2]=3;len=2;
    block[1].from=block[1].to=1;
    block[2].from=2;block[2].to=3;
    for(register int i=3;i<=2000000;i++){
        last[i]=last[i-1]+len;
        block[i].from=last[i-1]+1;
        block[i].to=last[i];
        if(i>=last[len])len++;
    }
    for(register int x=1;x<=2000000;x++){
        f[x]=f[x-1]+(block[x].to-block[x].from+1)*x*(block[x].to+block[x].from)/2%lk;
        f[x]%=lk;
    }
    scanf("%d",&t);
    for(register int i=1;i<=t;i++){
        scanf("%d",&n);
        l=1;r=2000000;
        while(l<=r){
            int mid=(l+r)>>1;
            if(block[mid].to<n) l=mid+1;
            else r=mid-1;
        }//二分查找
        cnt=f[r];
        cnt+=(r+1)*(n-block[r].to)*(block[r+1].from+n)/2%lk;
        cnt%=lk;
        printf("%I64d\n",cnt);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值