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

来源:互联网 发布:资金互助合作社软件 编辑:程序博客网 时间:2024/05/22 12:56
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 <bits/stdc++.h>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;}


原创粉丝点击