Naive Operations
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 502768/502768 K (Java/Others)
Total Submission(s): 1376 Accepted Submission(s): 575
Problem Description
In a galaxy far, far away, there are two integer sequence a and b of length n.
b is a static permutation of 1 to n. Initially a is filled with zeroes.
There are two kind of operations:
1. add l r: add one for al,al+1...ar
2. query l r: query ∑ri=l⌊ai/bi⌋
Input
There are multiple test cases, please read till the end of input file.
For each test case, in the first line, two integers n,q, representing the length of a,b and the number of queries.
In the second line, n integers separated by spaces, representing permutation b.
In the following q lines, each line is either in the form 'add l r' or 'query l r', representing an operation.
1≤n,q≤100000, 1≤l≤r≤n, there're no more than 5 test cases.
Output
Output the answer for each 'query', each one line.
Sample Input
5 12 1 5 2 4 3 add 1 4 query 1 4 add 2 5 query 2 5 add 3 5 query 1 5 add 2 4 query 1 4 add 2 5 query 2 5 add 2 2 query 1 5
Sample Output
1 1 2 4 4 6
题意:给定一个a数组,初始全为0,给定一个b数组,为1-n的全排列,有两种操作:
1、对a数组的l,r区间加1
2、求l,r区间a[i]/b[i]向下取整的值
题解:一开始看错题了啊!!!给自己出个极端数据,b数组全是1,完全卡死,结果根本不可能有这样的数组。。因为是全排列,所以最坏情况直播大佬说是调和级数,也就是nlogn,所以放心大胆乱搞吧!开两个线段树,第一个线段树记录最小值,当区间加一时,该线段树区间减一,加延时标记,当有最小值为0时,更新0成对应的b数组的值,并更新对应sum+1,sum即为第二个线段树,统计区间和,只有当对应位置的第一个线段树变成0,sum对应位置才需要加1(向下取整)
故只需要多一个update更新函数即可!
代码
#include <stdio.h>
#include <iostream>
#include <string.h>
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
int min(int a, int b){
return a < b ? a : b;
}
using namespace std;
const int maxn = 100010, inf = 1e8;
int Min[maxn << 2], sum[maxn << 2], lazy[maxn << 2], a[maxn], b[maxn];
void push_up(int rt){
Min[rt] = min(Min[rt << 1], Min[rt << 1 | 1]);
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}
void push_down(int rt){
if(lazy[rt] != 0){
lazy[rt << 1] += lazy[rt];
lazy[rt << 1 | 1] += lazy[rt];
Min[rt << 1] -= lazy[rt];
Min[rt << 1 | 1] -= lazy[rt];
lazy[rt] = 0;
}
}
void bulid(int l, int r, int rt){
Min[rt] = inf;
lazy[rt] = 0;
if(l == r){
scanf("%d", &b[l]);
Min[rt] = b[l];
return ;
}
int m = (l + r) >> 1;
bulid(lson);
bulid(rson);
push_up(rt);
}
int update(int L,int R, int l, int r, int rt){
if(L <= l && r <= R){
lazy[rt]+=1;
Min[rt]--;
if(Min[rt] == 0)
return 0;
else
return 1;
}
push_down(rt);
int m = (l + r) >> 1;
int ans = 1;
if(L <= m)
ans = min(ans, update(L, R, lson));
if(R > m)
ans = min(ans, update(L, R, rson));
push_up(rt);
return ans;
}
void update1(int L, int R, int l, int r, int rt){
if(l == r){
if(Min[rt] == 0){
Min[rt] = b[l];
sum[rt]++;
}
return ;
}
push_down(rt);
int m = (l + r) >> 1;
if(Min[rt << 1] == 0)
update1(L, R, lson);
if(Min[rt << 1 | 1] == 0)
update1(L, R, rson);
push_up(rt);
}
int query(int L, int R,int l, int r, int rt){
if(L <= l && r <= R){
return sum[rt];
}
int m = (l + r) >> 1;
int ret = 0;
if(m >= L)
ret += query(L, R, lson);
if(R > m)
ret += query(L, R, rson);
return ret;
}
int main(){
// freopen("in.txt", "r", stdin);
int n, m, x, y, z;
char t[11];
while(scanf("%d %d", &n, &m) != EOF){
memset(sum, 0, sizeof(sum));
bulid(1, n, 1);
for(int i = 0; i < m; i++){
scanf("%s %d %d", t, &x, &y);
if(t[0] == 'a'){
z = update(x, y, 1, n, 1);
if(z == 0)
update1(x, y, 1, n, 1);
}
else
printf("%d\n", query(x, y, 1, n, 1));
}
}
return 0;
}