zoukankan      html  css  js  c++  java
  • BZOJ 2120 数颜色

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2120

    题意:给出一个数列,两种操作:(1)询问区间[L,R]内有多少不同的数字;(2)修改某个位置的数字。

    思路:首先分块。然后用sum[L][R][x]记录从第L块到第R块数字x出现的次数,cnt[L][R] 表示从第L块到第R块不同数字的个数。分块后可以预处理出初始时的sum和cnt数组。对于查询,[L,R],可能不是完整占据某段连续的块,需要将零头加上,之后输出答案再将零头减去;对于修改,找到包含修改位置所在块的所有区间修改sum和cnt数组。

     




    int pl[25],pr[25],pNum,cnt[25][25],sum[25][25][N];
    int f[N*100],K,size;
    int n,m;
    int a[N];


    int F(int k)
    {
        if(!f[k]) f[k]=++K;
        return f[k];
    }




    void deal()
    {
        int x,y,i,j,k,ll,rr;
        char op[5];
        while(m--)
        {
            RD(op); RD(x,y);
            if(op[0]=='Q')
            {
                ll=0; rr=pNum;
                while(pl[ll]<x) ll++;
                while(pr[rr]>y) rr--;
                for(i=x;i<=min(y,pr[ll-1]);i++)
                {
                    if(++sum[ll][rr][a[i]]==1) cnt[ll][rr]++;
                }
                for(i=max(x,pl[rr+1]);i<=y;i++)
                {
                    if(++sum[ll][rr][a[i]]==1) cnt[ll][rr]++;
                }
                PR(cnt[ll][rr]);
                for(i=x;i<=min(y,pr[ll-1]);i++)
                {
                    if(0==--sum[ll][rr][a[i]]) cnt[ll][rr]--;
                }
                for(i=max(x,pl[rr+1]);i<=y;i++)
                {
                    if(0==--sum[ll][rr][a[i]]) cnt[ll][rr]--;
                }
            }
            else
            {
                k=0;
                while(pr[k]<x) k++;
                for(i=1;i<=k;i++) for(j=k;j<=pNum;j++)
                {
                    if(0==--sum[i][j][a[x]]) cnt[i][j]--;
                }
                a[x]=F(y);
                for(i=1;i<=k;i++) for(j=k;j<=pNum;j++)
                {
                    if(1==++sum[i][j][a[x]]) cnt[i][j]++;
                }
            }
        }
    }


    int main()
    {
        RD(n,m);
        int i,j,k;
        FOR1(i,n) RD(j),a[i]=F(j);
        while(size*size*size<n) size++;
        size=size*size;
        int L=1,R=min(n,size);
        while(L<=n)
        {
            pl[++pNum]=L;
            pr[pNum]=R;
            L=R+1;
            R=min(n,R+size);
        }
        FOR1(i,pNum) for(j=i;j<=pNum;j++)
        {
            for(k=pl[i];k<=pr[j];k++)
            {
                if(++sum[i][j][a[k]]==1) cnt[i][j]++;
            }
        }
        pl[0]=-INF; pr[0]=0; pl[++pNum]=n+1; pr[pNum]=INF;
        deal();
    }

  • 相关阅读:
    第三方登录(QQ登录)开发流程详解
    网页优化方案
    linux中PHP链接MySQL主机127.0.0.1与localhost
    RSync实现文件备份同步
    网站攻击以及解决方案
    迎难而上,QPS提高22+倍
    新的一扇窗
    边缘计算开源平台
    高并发分布式计算-生产实践
    分布式UUID的生成
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/3460040.html
Copyright © 2011-2022 走看看