您的位置:首页 > 其它

PKU 4047 - Garden(线段树 + 区间修改)

2014-10-05 15:13 351 查看


题意

给出三个操作。单点更新,交换两个点,区间询问。

询问的时候要求输出区间内k个值的最大和。


思路

一开始想着维护k个值的最大和,没思路。

后来想到可以把k个值压缩成一个点,这样就变成普通的线段树了。

这样的话,当修改一个点时,影响的新的区间是l = max(1, n - k + 1), r = min(N - k + 1, n).

交换,单点更新都可以看成某个区间内增加一个值。


代码

#include <cstdio>

#include <stack>

#include <set>

#include <iostream>

#include <string>

#include <vector>

#include <queue>

#include <functional>

#include <cstring>

#include <algorithm>

#include <cctype>

#include <ctime>

#include <cstdlib>

#include <fstream>

#include <string>

#include <sstream>

#include <map>

#include <cmath>

#define LL long long

#define SZ(x) (int)x.size()

#define Lowbit(x) ((x) & (-x))

#define MP(a, b) make_pair(a, b)

#define MS(arr, num) memset(arr, num, sizeof(arr))

#define PB push_back

#define F first

#define S second

#define ROP freopen("input.txt", "r", stdin);

#define MID(a, b) (a + ((b - a) >> 1))

#define LC rt << 1, l, mid

#define RC rt << 1|1, mid + 1, r

#define LRT rt << 1

#define RRT rt << 1|1

#define BitCount(x) __builtin_popcount(x)

const double PI = acos(-1.0);

const int INF = 0x3f3f3f3f;

using namespace std;

const LL MAXN = 2e5 + 10;

const int MOD = 20071027;


typedef pair<int, int> pii;

typedef vector<int>::iterator viti;

typedef vector<pii>::iterator vitii;


int num[MAXN], n, m, k;

vector<int> sum;


struct SEGTREE

{

int add, nmax;

}segt[MAXN << 2];


void PushUp(int rt)

{

segt[rt].nmax = max(segt[LRT].nmax, segt[RRT].nmax);

}


void PushDown(int rt)

{

const int &add = segt[rt].add;

segt[LRT].nmax += add;

segt[RRT].nmax += add;

segt[LRT].add += add;

segt[RRT].add += add;

segt[rt].add = 0;

}


int Query(int rt, int l, int r, int L, int R)

{

if (L <= l && r <= R) return segt[rt].nmax;

if (segt[rt].add) PushDown(rt);

int mid = MID(l, r);

int ret = -INF;

if (L <= mid) ret = max(ret, Query(LC, L, R));

if (R > mid) ret = max(ret, Query(RC, L, R));

return ret;

}


void Update(int rt, int l, int r, int L, int R, int val)

{

if (L <= l && r <= R)

{

segt[rt].add += val;

segt[rt].nmax += val;

return;

}

if (segt[rt].add) PushDown(rt);

int mid = MID(l, r);

if (L <= mid) Update(LC, L, R, val);

if (R > mid) Update(RC, L, R, val);

PushUp(rt);

}


void Build(int rt, int l, int r)

{

segt[rt].add = 0;

if (l == r)

{

segt[rt].nmax = sum[l];

return;

}

int mid = MID(l, r);

Build(LC); Build(RC);

PushUp(rt);

}


void Solve()

{

const int N = n - k + 1;

int a, b, c;

while (m--)

{

scanf("%d%d%d", &a, &b, &c);

if (a == 0)

{

int val = c - num[b];

num[b] = c;

Update(1, 1, N, max(1, b - k + 1), min(b, N), val);

}

else if (a == 1)

{

int val = num[c] - num[b];

Update(1, 1, N, max(1, b - k + 1), min(b, N), val);

val = num[b] - num[c];

swap(num[b], num[c]);

Update(1, 1, N, max(1, c - k + 1), min(c, N), val);

}

else printf("%d\n", Query(1, 1, N, b, c - k + 1));

}

}


int main()

{

//ROP;

int T, i, j;

scanf("%d", &T);

while (T--)

{

sum.clear(); sum.PB(9999); sum.PB(0);

scanf("%d%d%d", &n, &m, &k);

int temp = 0;

for (i = 1; i <= n; i++)

{

scanf("%d", &num[i]);

temp += num[i];

if (i > k)

{

temp -= num[i - k];

sum.PB(temp);

}

else sum.back() = temp;

}

Build(1, 1, n - k + 1);

Solve();

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM PKU