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

CodeChef:Chef and Subarray Queries(线段树)

2017-11-22 19:27 357 查看




思路:求值在[L,R]之间的题目,往往转化成求[1,R]-[1,L-1],然后这题用线段树处理,每个节点计算当前区间的答案,主要思考合并操作的写法,代码思路还是比较简单的。

# include <iostream>
# include <cstdio>
# define lson l,m,id<<1
# define rson m+1, r, id<<1|1
using namespace std;
typedef long long LL;
const int maxn = 5e5+30;
struct node
{
int left, right, len;
LL ans;
};
node a[maxn<<4], b[maxn<<4];
node merge(node &ta, node &tb)
{
node res;
res.ans = ta.ans + tb.ans;
res.ans += 1LL*ta.right*tb.left;
res.len = ta.len + tb.len;
res.left = ta.left;
res.right = tb.right;
if(ta.left == ta.len) res.left += tb.left;
if(tb.right == tb.len) res.right += ta.right;
return res;
}
void build(node arr[], int l, int r, int id)
{
if(l == r)
{
arr[id].left = arr[id].right = arr[id].len = 1;
arr[id].ans = 1LL;
return;
}
int m = l+r>>1;
build(arr, lson);
build(arr, rson);
arr[id] = merge(arr[id<<1], arr[id<<1|1]);
}

void update(node arr[], int pos, int val, int l, int r, int id)
{
if(l == r)
{
arr[id].ans = 1LL*val;
arr[id].left = arr[id].right = val;
return;
}
int m = l+r>>1;
if(pos <= m) update(arr, pos, val, lson);
else update(arr, pos, val, rson);
arr[id] = merge(arr[id<<1], arr[id<<1|1]);
}

node query(node arr[], int L, int R, int l, int r, int id)
{
if(L <= l && R >= r)
return arr[id];
int m = l+r>>1;
node tl = {0,0,0,0}, tr = {0,0,0,0};
if(L <= m) tl = query(arr, L, R, lson);
if(R > m) tr = query(arr, L, R, rson);
return merge(tl, tr);
}
int main()
{
int n, q, l, r;
scanf("%d%d%d%d",&n,&q,&l,&r);
build(a, 1, n, 1);
build(b, 1, n, 1);
while(q--)
{
int op, x, y;
scanf("%d%d%d",&op,&x,&y);
if(op == 1)
{
if(y <= r) update(a, x, 1, 1, n, 1);
else update(a, x, 0, 1, n, 1);
if(y < l) update(b, x, 1, 1, n, 1);
else update(b, x, 0, 1, n, 1);
}
else
{
LL ans = 0;
ans = query(a, x, y, 1, n, 1).ans-query(b, x, y, 1, n, 1).ans;
printf("%lld\n",ans);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: