BZOJ 3236: [Ahoi2013]作业( 莫队 + BIT )

莫队..用两个树状数组计算.时间复杂度应该是O(N1.5logN). 估计我是写残了...跑得很慢...

-------------------------------------------------------------------------

#include<bits/stdc++.h>

using namespace std;

#define lowbit(x) ((x) & -(x))

const int maxn = 100009;

const int maxm = 1000009;

int N, M, block[maxn], seq[maxn], ans[maxm][2], L, R;

inline int read() {

int ans = 0;

char c = getchar();

for(; !isdigit(c); c = getchar());

for(; isdigit(c); c = getchar())

ans = ans * 10 + c - ‘0‘;

return ans;

}

int buf[12];

inline void write(int x) {

if(!x) {

putchar(‘0‘);

return;

}

int n = 0;

for(; x; x /= 10) buf[n++] = x % 10;

while(n--) putchar(buf[n] + ‘0‘);

}

struct BIT {

int b[maxn];

BIT() {

memset(b, 0, sizeof b);

}

inline void update(int x, int v) {

for(; x <= N; x += lowbit(x)) b[x] += v;

}

inline int sum(int x) {

int ret = 0;

for(; x; x -= lowbit(x)) ret += b[x];

return ret;

}

inline int query(int l, int r) {

return sum(r) - sum(l - 1);

}

} cnt, exist;

struct Q {

int l, r, a, b, p;

inline void Read(int t) {

l = read() - 1; r = read() - 1;

a = read(); b = read();

p = t;

}

bool operator < (const Q &o) const {

return block[l] < block[o.l] || (block[l] == block[o.l] && r < o.r);

}

} A[maxm];

void init() {

N = read(); M = read();

for(int i = 0; i < N; i++) seq[i] = read();

int blocks = (int) sqrt(N);

for(int i = 0; i < N; i++) block[i] = i / blocks;

for(int i = 0; i < M; i++) A[i].Read(i);

}

void work(int x) {

Q* c = A + x;

for(; L < c->l; L++) {

cnt.update(seq[L], -1);

if(!cnt.query(seq[L], seq[L])) exist.update(seq[L], -1);

}

while(L > c->l) {

L--;

if(!cnt.query(seq[L], seq[L])) exist.update(seq[L], 1);

cnt.update(seq[L], 1);

}

for(; R > c->r; R--) {

cnt.update(seq[R], -1);

if(!cnt.query(seq[R], seq[R])) exist.update(seq[R], -1);

}

while(R < c->r) {

R++;

if(!cnt.query(seq[R], seq[R])) exist.update(seq[R], 1);

cnt.update(seq[R], 1);

}

ans[c->p][0] = cnt.query(c->a, c->b);

ans[c->p][1] = exist.query(c->a, c->b);

}

int main() {

init();

sort(A, A + M);

cnt.update(seq[L = R = 0], 1);

exist.update(seq[0], 1);

for(int i = 0; i < M; i++) work(i);

for(int i = 0; i < M; i++) {

write(ans[i][0]);

putchar(‘ ‘);

write(ans[i][1]);

putchar(‘\n‘);

}

return 0;

}

-------------------------------------------------------------------------

3236: [Ahoi2013]作业

Time Limit: 100 Sec  Memory Limit: 512 MB
Submit: 899  Solved: 345
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

3 4
1 2 2
1 2 1 3
1 2 1 1
1 3 1 3
2 3 2 3

Sample Output

2 2
1 1
3 2
2 1

HINT

N=100000,M=1000000

Source

By wangyisong1996加强数据

时间: 2024-11-05 11:39:00

BZOJ 3236: [Ahoi2013]作业( 莫队 + BIT )的相关文章

bzoj 3236: [Ahoi2013]作业(缺线段树)

3236: [Ahoi2013]作业 Time Limit: 100 Sec  Memory Limit: 512 MBSubmit: 1744  Solved: 702[Submit][Status][Discuss] Description Input Output Sample Input 3 4 1 2 2 1 2 1 3 1 2 1 1 1 3 1 3 2 3 2 3 Sample Output 2 2 1 1 3 2 2 1 HINT N=100000,M=1000000 Sourc

BZOJ 3236: [Ahoi2013]作业

题目 3236: [Ahoi2013]作业 Time Limit: 100 Sec  Memory Limit: 512 MBSubmit: 732  Solved: 271 Description Input Output Sample Input 3 4 1 2 2 1 2 1 3 1 2 1 1 1 3 1 3 2 3 2 3 Sample Output 2 2 1 1 3 2 2 1 HINT N=100000,M=1000000 Source By wangyisong1996加强数据

[BZOJ 3236] [Ahoi2013] 作业 &amp;&amp; [BZOJ 3809] 【莫队 | 分块】

题目链接: BZOJ - 3236   BZOJ - 3809 算法一:莫队 首先,单纯的莫队算法是很好想的,就是用普通的第一关键字为 l 所在块,第二关键字为 r 的莫队. 这样每次端点移动添加或删除一个数字,用树状数组维护所求的信息就是很容易的.由于这里有 logn复杂度,所以复杂度还是挺高的. 于是 BZOJ-3236 的时限 100s,我的代码跑了 98s,险过...... However..BZOJ-3809 的出题人(SLYZ的神犇)就没有这么善良了!直接内存限制 28MB 就直接把

树套树专题——bzoj 3110: [Zjoi2013] K大数查询 &amp; 3236 [Ahoi2013] 作业 题解

[原题1] 3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 978  Solved: 476 Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M 接下来M行,每行形如1 a b c或2 a b c Outpu

BZOJ 3236 AHOI 2013 作业 莫队算法

题目大意:给出一些数,问在一个区间中不同的数值有多少种,和在一个区间中不同的数值有多少个. 思路:由于没有修改,所以就想到了莫队算法.然后我写了5K+的曼哈顿距离最小生成树,然后果断T了.(100s的时限啊,刷status都要刷疯了..,结果最后加了手写读入也没能A).后来果断放弃,写了分块版的莫队算法.84sAC...这题卡的..貌似莫队并不是正解. 其实用分块来写莫队就很简单了.只需要将所有询问的区间排序,左端点所在块作为第一键值,右端点作为第二季键值排序,之后就可以转移了.理论上来时还是曼

[BZOJ 3585] mex 【莫队+分块】

题目链接:BZOJ - 3585 题目分析 区间mex,即区间中没有出现的最小自然数. 那么我们使用一种莫队+分块的做法,使用莫队维护当前区间的每个数字的出现次数. 然后求mex用分块,将权值分块(显然mex 一定小于等于 n ,大于 n 的权值没有意义,可以直接忽略),每块大小 sqrt(n) . 然后区间中的某个数的数量被减到0的时候就将它所在的块的种类计数减一,添加数的时候类似. 然后枚举每个块,找到最小的中间有数不存在的块(即种类数小于块中的数的种数),然后到这个快里直接从小一个一个找到

BZOJ 3757 苹果树 树上莫队

题目大意:给出一棵树,问任意两点之间有多少种不同的颜色,一个人可能会有色盲,会将A和B当成一种颜色. 思路:比较裸的树上莫队,写出来之后,很慢,怀疑是分块的缘故,然后果断找了当年比赛的标称交上去,瞬间rk1,大概看了一眼,他好像是直接用DFS序+曼哈顿距离最小生成树搞的,为什么会比分块快? 昨天下午看到这个题之后就一直在研究树上莫队的正确姿势,然后先写了树分块,后来看了很多牛人的SPOJ COT2的题解,后来又和同学探讨了好久才弄明白. 首先先将树分块,然后把区间排序,按照第一权值为左端点所在块

【BZOJ】4358: permu 莫队算法

[题意]给定长度为n的排列,m次询问区间[L,R]的最长连续值域.n<=50000. [算法]莫队算法 [题解]考虑莫队维护增加一个数的信息:设up[x]表示数值x往上延伸的最大长度,down[x]表示数值x往下延伸的最大长度. 增加一个数x时,up[x]=up[x+1]+1,down[x]=down[x-1]+1.令t=up[x]+down[x]+1,可以用于更新答案. 同时,增加x后会影响到x所在连续区间最大数和最小数,中间的数字不会影响答案(只考虑加数),所以有: down[x+up[x]

【BZOJ 3236】 [Ahoi2013]作业

3236: [Ahoi2013]作业 Time Limit: 100 Sec Memory Limit: 512 MB Submit: 819 Solved: 307 [Submit][Status][Discuss] Description Input Output Sample Input 3 4 1 2 2 1 2 1 3 1 2 1 1 1 3 1 3 2 3 2 3 Sample Output 2 2 1 1 3 2 2 1 HINT N=100000,M=1000000 Source