HDU 5057 Argestes and Sequence 离线处理+树状数组

HDU 5057
题意:给出n个数的序列a,m个操作. n,m<=1e5,a[i]<=1e9.
操作1:[s,x,y] 将第x个数设置成y a[x]=y.
操作2:[q,l,r,d,p] 问[l,r]内有多少个数的第D位(从低位开始数)正好是数字P.


关键:离线一位一位处理,假如现在处理的都是:关于第i位的询问.

遍历序列中的每个数,将每个数的第i位都仍到树状数组中,BIT要多加一维 标志当前这个位置第i位出现的是那个数字

#include 
using namespace std;
const int N=2e5+20;
struct node{
    int flag,x,y,l,r,d,p,ans;
}q[N];
int a[N],c[N][10],pos[N];
int T,n,m;
int lowbit(int x){return x&-x;}
void update(int x,int num,int value)
{
    for(int i=x;i<=n;i+=lowbit(i))
        c[i][num]+=value;
}
int query(int x,int num)
{
    int res=0;
    for(int i=x;i>0;i-=lowbit(i))
        res+=c[i][num];
    return res;
}
int main()
{
    char op[10];
    cin>>T;
    while(T--)
    {
        memset(c,0,sizeof(c));
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<=m;i++)
        {
            scanf("%s",op);
            if(op[0]=='Q')
            {
                q[i].flag=1;
                scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].d,&q[i].p);
            }
            else
            {
                q[i].flag=0;
                scanf("%d%d",&q[i].x,&q[i].y);
            }
        }
        int pw=1;
        for(int i=1;i<=10;i++)
        {
            memset(c,0,sizeof(c));
            for(int j=1;j<=n;j++)
            {
                pos[j]=a[j]/pw%10;
                update(j,pos[j],1);
            }
            for(int j=1;j<=m;j++)
            {
                if(q[j].flag==1&&q[j].d==i)
                    q[j].ans=query(q[j].r,q[j].p)-query(q[j].l-1,q[j].p);
                else if(q[j].flag==0)
                {
                    update(q[j].x,pos[q[j].x],-1);
                    update(q[j].x,q[j].y/pw%10,1);
                    pos[q[j].x]=q[j].y/pw%10;
                }
            }
            pw*=10;
        }
        for(int i=1;i<=m;i++)
            if(q[i].flag==1)
                printf("%d\n",q[i].ans);
    }
    return 0;
}


你可能感兴趣的:(HDU)