Time Limit: 3 second(s) | Memory Limit: 64 MB |
You have an array with n elements which is indexed from 0 to n - 1. Initially all elements are zero. Now you have to deal with two types of operations
1. Increase the numbers between indices i and j (inclusive) by 1. This is represented by the command '0 i j'.
2. Answer how many numbers between indices i and j (inclusive) are divisible by 3. This is represented by the command '1 i j'.
Input
Input starts with an integer T (≤ 5), denoting the number of test cases.
Each case starts with a line containing two integers n (1 ≤ n ≤ 105) and q (1 ≤ q ≤ 50000) denoting the number of queries. Each query will be either in the form '0 i j' or '1 i j' where i, j are integers and 0 ≤ i ≤ j < n.
Output
For each case, print the case number first. Then for each query in the form '1 i j', print the desired result.
Sample Input | Output for Sample Input |
1 10 9 0 0 9 0 3 7 0 1 4 1 1 7 0 2 2 1 2 4 1 8 8 0 5 8 1 6 9 | Case 1: 2 3 0 2 |
Note
Dataset is huge, use faster i/o methods.
题意:0-n-1的数,m次操作,每次有0往区间添加1,和1,询问区间能被3整除的数字个数输出。
思路:之前一直卡TLE。线段树更新区间的话,要用懒标记法,不然会TLE。第一次写有点搓。每个结点存放mod为0,mod为1,mod为2的数字个数,和一个标记v。如果加一,就是把3个数字换一下。
代码:
#include <stdio.h>
#include <string.h>
#define max(a,b) ((a)>(b)?(a):(b))
const int N = 1000005;
int t, n, Q;
struct Tree {
int l, r, mod0, mod1, mod2, v;
}st[N];
void build(int l, int r, int id) {
if (l != r) {
int mid = (l + r) / 2;
build(l, mid, 2 * id);
build(mid + 1, r, 2 * id + 1);
}
st[id].l = l; st[id].r = r;
if (l == r)
st[id].mod0 = 1;
else
st[id].mod0 = st[id * 2].mod0 + st[id * 2 + 1].mod0;
st[id].mod1 = st[id].mod2 = st[id].v = 0;
}
void tra(Tree &t) {
int t0 = t.mod0, t1 = t.mod1, t2 = t.mod2;
t.mod0 = t2; t.mod1 = t0; t.mod2 = t1;
}
void Insert(int l, int r, int id) {
if (l == st[id].l && r == st[id].r) {
tra(st[id]);
st[id].v++;
return;
}
if (st[id].v) {
int t = st[id].v;
st[id].v = 0;
st[id * 2].v += t;
st[id * 2 + 1].v += t;
t %= 3;
while (t--) {
tra(st[id * 2]);
tra(st[id * 2 + 1]);
}
}
int mid = (st[id].l + st[id].r) / 2;
if (l <= mid && r > mid) {
Insert(l, mid, id * 2);
Insert(mid + 1, r, id * 2 + 1);
}
else if (r <= mid) Insert(l, r, id * 2);
else Insert(l, r, id * 2 + 1);
st[id].mod0 = st[id * 2].mod0 + st[id * 2 + 1].mod0;
st[id].mod1 = st[id * 2].mod1 + st[id * 2 + 1].mod1;
st[id].mod2 = st[id * 2].mod2 + st[id * 2 + 1].mod2;
}
int Query(int l, int r, int id) {
if (l == st[id].l && r == st[id].r) {
return st[id].mod0;
}
if (st[id].v) {
int t = st[id].v;
st[id].v = 0;
st[id * 2].v += t;
st[id * 2 + 1].v += t;
t %= 3;
while (t--) {
tra(st[id * 2]);
tra(st[id * 2 + 1]);
}
}
int mid = (st[id].l + st[id].r) / 2;
if (l <= mid && r > mid) {
return Query(l, mid, id * 2) + Query(mid + 1, r, id * 2 + 1);
}
else if (r <= mid) return Query(l, r, id * 2);
else return Query(l, r, id * 2 + 1);
}
void init() {
memset(st, 0, sizeof(st));
scanf("%d%d", &n, &Q);
build(0, n - 1, 1);
}
void solve() {
int a, b, c;
while (Q--) {
scanf("%d%d%d", &a, &b, &c);
if (a == 0)
Insert(b, c, 1);
else
printf("%d\n", Query(b, c, 1));
}
}
int main() {
int cas = 0;
scanf("%d", &t);
while (t--) {
printf("Case %d:\n", ++cas);
init();
solve();
}
return 0;
}