您的位置:首页 > 产品设计 > UI/UE

HDU 5057 Argestes and Sequence 分块

2015-12-04 20:00 453 查看

题意:给N个数,有两种操作,S x y 将a[x]变为y;Q x y d p 寻找[x,y]之内第d位的数为p的个数。

思路:开始一想,裸的线段树呀,敲了之后,MLE,然后一愣,有点傻眼了,卡空间。然而正解是分块,就是把N分成N−−√\sqrt{N}份,再处理,写跪了N发之后才A。也是爽。各种WA,TLE。复杂度N*N−−√\sqrt{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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: