线段树的应用。先创建一个线段树,并且初始化各个节点。再通过update函数进行更新,在update里调用push_down和push_down,进而更新节点,最后通过query函数进行访问。线段树之所以能使复杂度下降,就是利用节点访问,进而避免遍历整个数据而造成浪费。
#include <iostream>
#include <stdio.h>
#include <memory.h>
using namespace std;
int sum[400020],setv[400020];
int _sum;
void build(int rt,int L,int R)
{
if(L == R) sum[rt] = 1;
else
{
int M = (L + R) / 2;
build(2 * rt,L,M);
build(2 * rt + 1,M + 1,R);
sum[rt] = sum[rt * 2] + sum[rt * 2 + 1];
}
}
void push_up(int rt,int L,int R)
{
int lc = 2 * rt;int rc = 2 * rt + 1;
sum[rt] = sum[lc] + sum[rc];
if(setv[rt] > 0)
sum[rt] = setv[rt] * (R - L + 1);
}
void push_down(int rt)
{
int lc = rt * 2;int rc = rt * 2 + 1;
if(setv[rt] >= 1)
{
setv[lc] = setv[rc] = setv[rt];
setv[rt] = 0;
}
}
void update(int rt,int L,int R,int x,int y,int v)
{
if(x <= L && y >= R) {setv[rt] = v;sum[rt] = v * (R - L + 1);}
else
{
push_down(rt);
int M = (L + R) / 2;
if(x <= M) update(2 * rt,L,M,x,y,v);
else push_up(2 * rt,L,M);
if(y > M) update(2 * rt + 1,M + 1,R,x,y,v);
else push_up(2 * rt + 1,M + 1,R);
push_up(rt,L,R);
}
}
void query(int rt,int L,int R,int ql,int qr)
{
if(setv[rt] > 0) _sum += setv[rt] * (min(qr,R) - max(ql,L) + 1);
else if(ql <= L && qr >= R)
{
_sum += sum[rt];
}
else
{
int M = (L + R) / 2;
if(ql <= M) query(rt * 2,L,M,ql,qr);
if(qr > M) query(rt * 2 + 1,M + 1,R,ql,qr);
}
}
int main()
{
int T,N,Q,t = 1; cin >> T;
while(T --)
{
memset(setv,0,sizeof(0));
cin >> N >> Q;
build(1,1,N);
setv[1] = 1;
int x,y,v;
for(int i = 0;i < Q;i ++)
{
cin >> x >> y >> v;
update(1,1,N,x,y,v);
}
_sum = 0;
query(1,1,N,1,N);
cout << "Case " << t ++ << ": The total value of the hook is " << _sum << "." << endl;
}
return 0;
}