HDU 5057 Argestes and Sequence 分块

题意:给N个数,有两种操作,S x y 将a[x]变为y;Q x y d p 寻找[x,y]之内第d位的数为p的个数。
思路:开始一想,裸的线段树呀,敲了之后,MLE,然后一愣,有点傻眼了,卡空间。然而正解是分块,就是把N分成 N 份,再处理,写跪了N发之后才A。也是爽。各种WA,TLE。复杂度N* N

http://acm.hdu.edu.cn/showproblem.php?pid=5057

/*********************************************
    Problem : HDU 5057
    Author  : NMfloat
    InkTime (c) NM . All Rights Reserved .
********************************************/

#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

#define rep(i,a,b)  for(int i = a ; i <= b ; i ++)
#define rrep(i,a,b) for(int i = b ; i >= a ; i --)
#define repE(p,u) for(Edge * p = G[u].first ; p ; p = p -> next)
#define cls(a,x)   memset(a,x,sizeof(a))
#define lson rt<<1
#define rson rt<<1|1

using namespace std;

const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e5+5;
const int MAXE = 2e5+5;

typedef long long LL;

int T,n,m,k;

int A[400][11][10];//最多分成300+块。
int NUM[MAXN];

int st,lt;
int tmp;

void START() {
    st = sqrt(n);//块的长度.
    lt = st * st == n ? st : st + 1;
    int base = 0;
    cls(A,0);
    rep(i,1,lt) {
        //一共有lt段;
        rep(j,1,st) {
            if(base+j > n) return ;
            tmp = NUM[base + j]; 
            rep(ia,1,10) {
                A[i][ia][tmp%10] ++;
                tmp /= 10;
            }
        }
        base += st;
    }
}

void out() {
    rep(i,1,n) printf("%d ",NUM[i]);
    puts("\n");
    printf("st : %d lt : %d\n\n",st,lt);
    rep(i,1,lt) {
        rep(ia,1,10) {
            rep(ib,0,9) {
                printf("%d ",A[i][ia][ib]);
            }
            puts("");
        } 
        puts("");
    }
    puts("\n");
}

void Update(int pos,int num) {
    int oldnum = NUM[pos];
    NUM[pos] = num;
    int nowpos = (pos + (st - 1)) / st; //表示pos在第几个区间。

    tmp = oldnum; 
    rep(ia,1,10) {
        A[nowpos][ia][tmp%10] --;
        tmp /= 10;
    }

    tmp = num; 
    rep(ia,1,10) {
        A[nowpos][ia][tmp%10] ++;
        tmp /= 10;
    }
}

int ANS ;
int digit[11];

void Query(int left,int right,int d,int p) {
    //计算1..(left-1) 1..right的值
    // int nowpos = (left - 1) / st;
    // int leftans = 0;
    // rep(i,1,nowpos) {
    //     leftans += A[i][d][p];
    // } 
    // rep(i,nowpos * st + 1,left-1) {
    //     tmp = NUM[i]; 
    //     rep(ia,1,10) {
    //         if((ia == d) && (tmp % 10 == p)) leftans ++;
    //         tmp /= 10;
    //     }
    // }

    // nowpos = right / st ;
    // int rightans = 0;
    // rep(i,1,nowpos) {
    //     rightans += A[i][d][p];
    // } 
    // rep(i,nowpos * st + 1,right) {

    // }
    // ANS = rightans - leftans;
    int L = (left + st - 1 ) / st + 1; int R = (right + st - 1) / st - 1;
    //printf("L : %d R : %d\n",L,R);
    if(L > R) {
        rep(i,left,right) {
            if((NUM[i]/digit[d])%10==p)ANS ++;
        }
    }
    else {
        rep(i,L,R) {
            ANS += A[i][d][p];
        }
        rep(i,left,(L-1)*st) {
            if((NUM[i]/digit[d])%10==p)ANS ++;
        }
        rep(i,R*st+1,right) {
            if((NUM[i]/digit[d])%10==p)ANS ++;
        }
    }
} 

int ReadInt() { //可以读负数;
    char tempc; int minus = 1; int ret = 0; scanf("%c",&tempc);
    while(tempc < '0' || tempc > '9') { if(tempc == '-') minus = -1 ; scanf("%c",&tempc); }
    while(tempc >= '0' && tempc <= '9') { ret = ret * 10 + tempc - '0' ; scanf("%c",&tempc); }
    return ret * minus;
}

void input() {
    scanf("%d %d",&n,&m);
    //n = ReadInt(); m = ReadInt();
    char op[5];
    rep(i,1,n) scanf("%d",&NUM[i]); // NUM[i] = ReadInt();//
    digit[1] = 1;
    rep(i,2,10) digit[i] = digit[i-1] * 10;
    START();
    //out();
    int x,y,d,p;
    rep(i,1,m) {
        scanf("%s",op);
        if(op[0] == 'S') {
            // x = ReadInt(); y = ReadInt();
            scanf("%d %d",&x,&y);
            Update(x,y);
        }
        else {
            // x = ReadInt(); y = ReadInt();
            // d = ReadInt(); p = ReadInt();
            scanf("%d %d %d %d",&x,&y,&d,&p);
            ANS = 0;
            Query(x,y,d,p);
            printf("%d\n",ANS);
        }
    }
}

void solve() {

}

int main(void) {
    //freopen("a.in","r",stdin);
    scanf("%d",&T);
    while(T--) {
    //while(~scanf("%d %d",&n,&m)) {
        input();
        solve();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值