B1,B2 https://codeforces.com/contest/1234/problem/B2

题意:

模拟一个队列操作,队列有固定的长度,依次进队,如果已经在队中则跳过,如果不在队中,将队首元素出队,然后进队,输出最后队列的大小和依次顺序。

题解:

queue + pair 模拟一遍

代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxx = 200005;
map<int,int> mp;
queue<int> q;
int a[maxx];
int main()
{
    int n,k,x;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        if(q.size() < k)
        {
            if(mp[x] == 0){
                q.push(x);
                mp[x] = 1;
            }
            else{
                continue ;
            }
        }
        else{
            if(mp[x] == 0){
                mp[x] = 1;
                int now = q.front();
                mp[now] = 0;
                q.pop();
                q.push(x);
            }
            else{
                continue ;
            }
        }
    }
    int cnt = 0;
    while(!q.empty()){
        a[++cnt] = q.front();
        q.pop();
    }
    cout<<cnt<<endl;
    for(int i=cnt;i>=1;i--){
        cout<<a[i]<<" ";
    }
    return 0;
}

C:https://codeforces.com/contest/1234/problem/C

题意:

当时打完D再看的C,题意直接读错了。。。

题目意思:给出的六种管道,其实就相当于俩种管道,一种是直的,另一种是可以拐弯的,问你是否能从左上角流到右下角

题解:

分析单独一列的所有组合情况;如果俩个管道都是直,从前面任意一行流过来的管道都能流过去,如果俩个都是弯的管道,从前面一行的哪个位置流过来的水,都能通过旋转来将水流过去,如果一个是弯的管道一个是直的,无论如何都无法流过去。所以我们只需要模拟记录水流的位置是位于上方还是下方,往后遍历,如果存在一个弯的和一个直的或者最后水流位于上方就输出'NO',否则'YES'

代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
    int t,n;
    string s[3];
    cin>>t;
    while(t--)
    {
        int i, k = 0;
        cin>>n;
        cin>>s[0]>>s[1];
        for(i=0;i<n;i++)
        {
            if(s[k][i] > '2'){
                k = 1-k;
                if(s[k][i] <= '2'){
                    break;
                }
            }
        }
        if(k == 0 || i != n){
            printf("NO\n");
            continue ;
        }
        printf("YES\n");
    }
}

D:https://codeforces.com/contest/1234/problem/D

题意:

线段树的题意,给出一个字符串,俩个操作

1 x y 是将x位置的字符变成y ; 2 x y 询问[x,y]位置上有多少不同的字符

题解:

线段树板子应该可以过,不过优先考虑简单的写法,因为小写字符一共26个,我们只需要记录每个字符所在的位置存到set里即可,每次询问[x,y]区间的字符个数,只需遍历26个字符即可,具体看代码

代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxx = 100005;
set<int>  pos[27];
set<int>::iterator it;
char s[maxx];
int main()
{
    scanf("%s",s+1);
    int len = strlen(s+1) , n , x;
    for(int i=1;i<=len;i++){
        int k = s[i]-'a';
        pos[k].insert(i);
    }
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d",&x);
        if(x == 2)
        {
            int l , r ,cnt = 0;
            scanf("%d %d",&l,&r);
            for(int i=0;i<26;i++)
            {
                it = pos[i].lower_bound(l);
                //cout<<*it<<endl;
                if(*it <= r && *it >= l){
                    cnt++;
                }
            }
            cout<<cnt<<endl;
        }
        else{
            int p;
            char c;
            cin>>p>>c;
            getchar();
            int k = c-'a';
            char nowc = s[p];
            s[p] = c;
            pos[nowc-'a'].erase(p);
            pos[c-'a'].insert(p);
        }
    }
    return 0;
}