1 条题解

  • 0
    @ 2025-8-24 21:54:22

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 「QQ红包」
    **

    搬运于2025-08-24 21:54:22,当前版本为作者最后更新于2017-11-01 23:27:52,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    肯定有人学数据结构学傻了。直接用 vector记录每个颜色出现的位置,然后二分一下就好。

    因为颜色的范围很小,都不用离散。

    #include<bits/stdc++.h>
    using namespace std;
    int read()
    {
        char s;
        int k=0,base=1;
        while((s=getchar())!='-'&&s!=EOF&&!(s>='0'&&s<='9'));
        if(s==EOF)exit(0);
        if(s=='-')base=-1,s=getchar();
        while(s>='0'&&s<='9')
        {
            k=k*10+(s-'0');
            s=getchar();
        }
        return k*base;
    }
    void write(int x)
    {
        if(x<0)
        {
            putchar('-');
            write(-x);
        }
        else
        {
            if(x/10)write(x/10);
            putchar(x%10+'0');
        }
    }
    const int maxn=3e5+100;
    const int maxm=6e5+100;
    int n,m,bj,X,Y,Z,p1,p2;
    int a[maxn],ans;
    int tong[maxn];
    int t1[maxn],Max;
    int    t[11][maxn*2];
    vector<int> g[maxn];
    bool f1,f2,f3,f4;
    void xg(int i,int x,int d)//t[i][x]+=d;
    {
        int s=x;
        while (s<=n)
        {
            t[i][s]+=d;
            s+=(s&(-s));
        }
        return;
    }
    int qh(int i,int x)
    {
        int s=x,sum=0;
        while (s)
        {
            sum+=t[i][s];
            s-=(s&(-s));
        }
        return sum;
    }
    int main()
    {
        n=read();m=read();
        f4=true;
        for (int i=1;i<=n;i++) 
        {
            a[i]=read();
            Max=max(a[i],Max);
            if (tong[a[i]]!=0) f4=false;
            if (f4) tong[a[i]]=i;
            t1[a[i]]++;//cnt
        }
        if (Max<=10) f2=true; else f2=false;
    /*    if (n<=1000)//一千以内的 
        {
            while (m--)
            {
                bj=read();
                if (bj==1)
                {
                    ans=0;
                    X=read();Y=read();Z=read();
                    for (int i=X;i<=Y;i++)
                        if (a[i]==Z) ans++;
                    printf("%d\n",ans);
                } else
                {
                    X=read();
                    swap(a[X],a[X+1]);
                }
            }
            return 0;
        }
        if (f4)//每个颜色只出现了一次 
        {
            while (m--)
            {
                bj=read();
                if (bj==1)
                {
                    X=read();Y=read();Z=read();
                    if (X<=tong[Z]&&tong[Z]<=Y) printf("1\n"); else printf("0\n");
                } else
                { 
                    X=read();
                    //a[X],a[X+1];
                    tong[a[X]]++;
                    tong[a[X+1]]--;
                    swap(a[X],a[X+1]);
                }
            }
            return 0;
        }
        if (f2)//颜色小于10种,顺便说一下,不要用什么树状数组,前缀和维护一下就好 
        {
            for (int i=1;i<=n;i++) xg(a[i],i,1);
            while (m--)
            {
                bj=read();
                if (bj==1)
                {
                    X=read();Y=read();Z=read();
                    ans=qh(Z,Y)-qh(Z,X-1);
                    printf("%d\n",ans);
                } else
                {
                    X=read();
                    xg(a[X],X,-1);
                    xg(a[X],X+1,1);
                    xg(a[X+1],X+1,-1);
                    xg(a[X+1],X,1);
                    swap(a[X+1],a[X]);
                }
            }
            return 0;
        }*/
        //然后还有一个部分分:特殊性质1
        //这个如果r-l<=20,暴力这一部分,否则暴力l~l-1和r+1~n,然后用整个的出现次数减一下就好 
        for (int i=1;i<=n;i++) g[a[i]].push_back(i);
        while (m--)
        {
            bj=read();
            if (bj==1)
            {
                X=read();Y=read();Z=read();
                p1=lower_bound(g[Z].begin(),g[Z].end(),X)-g[Z].begin();//找第一个>=X的 
                p2=upper_bound(g[Z].begin(),g[Z].end(),Y)-g[Z].begin()-1;//找第一个<=Y的 
                if (p2<p1) printf("0\n"); //这个注意要判掉 
                else
                printf("%d\n",p2-p1+1);
            } else
            {
                X=read();
                if (a[X]==a[X+1]) continue;//修改,如果颜色相同不用改了 
                p1=lower_bound(g[a[X]].begin(),g[a[X]].end(),X)-g[a[X]].begin();
                g[a[X]][p1]++;
                p2=lower_bound(g[a[X+1]].begin(),g[a[X+1]].end(),X+1)-g[a[X+1]].begin();
                g[a[X+1]][p2]--;
                swap(a[X],a[X+1]);//记得换掉 
            }
        }
        return 0;
    }
    
    
    • 1

    信息

    ID
    1588
    时间
    1000ms
    内存
    250MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者