用线段树维护区间没有被损坏的路的最小值,最小值对应的下标,区间被损坏的路的个数。。。标记下穿的时候先传add,再传mark,传add的时候minv,add,mark都要加上add[o],传mark的时候,minv,mark都要取最大。。。


#include <iostream>
#include <queue> 
#include <stack> 
#include <map> 
#include <set> 
#include <bitset> 
#include <cstdio> 
#include <algorithm> 
#include <cstring> 
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 200005
#define maxm 20000005
#define eps 1e-10
#define mod 1000000007
#define INF 0x3f3f3f3f
#define lowbit(x) (x&(-x))
#define mp make_pair
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid 
#define rson o<<1 | 1, mid+1, R 
typedef long long LL;
typedef unsigned long long ULL;
//typedef int LL;
using namespace std;

int minv[maxn << 2];
int sum[maxn << 2];
int id[maxn << 2];
int add[maxn << 2];
int mark[maxn << 2];
int n, m, num, mi, idx;

void read(void)
{
	scanf("%d%d%d", &n, &m, &num);
}

void build(int o, int L, int R)
{
	sum[o] = 0, minv[o] = num, id[o] = L, add[o] = 0, mark[o] = -INF;
	if(L == R) return;
	int mid = (L + R) >> 1;
	build(lson);
	build(rson);
}

int query(int o, int L, int R, int ql, int qr)
{
	if(ql <= L && qr >= R) return sum[o];
	int mid = (L + R) >> 1, ans = 0;
	if(ql <= mid) ans += query(lson, ql, qr);
	if(qr > mid) ans += query(rson, ql, qr);
	return ans;
}

void pushdown(int o)
{
	if(add[o]) {
		minv[ls] += add[o];
		minv[rs] += add[o];
		add[ls] += add[o];
		add[rs] += add[o];
		mark[ls] += add[o];
		mark[rs] += add[o];
		add[o] = 0;
	}
	if(mark[o] != -INF) {
		minv[ls] = max(minv[ls], mark[o]);
		minv[rs] = max(minv[rs], mark[o]);
		mark[ls] = max(mark[ls], mark[o]);
		mark[rs] = max(mark[rs], mark[o]);
		mark[o] = -INF;
	}
}

void pushup(int o, int L, int R)
{
	sum[o] = sum[ls] + sum[rs];
	if(id[ls] == -1) minv[o] = minv[rs], id[o] = id[rs];
	else if(id[rs] == -1) minv[o] = minv[ls], id[o] = id[ls];
	else {
		if(minv[ls] > minv[rs]) minv[o] = minv[rs], id[o] = id[rs];
		else minv[o] = minv[ls], id[o] = id[ls];
	}
}

void updata(int o, int L, int R, int ql, int qr, int v, int k)
{
	if(ql <= L && qr >= R) {
		if(k == 1) {
			add[o] += v;
			mark[o] += v;
			minv[o] += v;
		}
		else {
			mark[o] = max(mark[o], v);
			minv[o] = max(minv[o], v);
		}

		return;
	}
	pushdown(o);
	int mid = (L + R) >> 1;
	if(ql <= mid) updata(lson, ql, qr, v, k);
	if(qr > mid) updata(rson, ql, qr, v, k);
	pushup(o, L, R);
}



void update(int o, int L, int R)
{
	if(L == R) {
		minv[o] = INF;
		id[o] = -1;
		sum[o]++;
		return;
	}
	pushdown(o);
	int mid = (L + R) >> 1;
	if(idx <= mid) update(lson);
	else update(rson);
	pushup(o, L, R);
}

int query_min(int o, int L, int R, int ql, int qr)
{
	if(ql <= L && qr >= R) {
		if(mi > minv[o]) mi = minv[o], idx = id[o];	
		return minv[o];
	}
	pushdown(o);
	int mid = (L + R) >> 1, ans = INF;
	if(ql <= mid) ans = min(ans, query_min(lson, ql, qr));
	if(qr > mid) ans = min(ans, query_min(rson, ql, qr));
	pushup(o, L, R);
	return ans;
}

void work(void)
{
	build(1, 1, n);
	int k, ans = 0, ql, qr, x;
	while(m--) {
		scanf("%d%d%d%d", &k, &ql, &qr, &x);
		if(k == 1) {
			if(query(1, 1, n, ql, qr) != 0) continue;
			ans++;
			updata(1, 1, n, ql, qr, -x, 1);
			mi = INF;
			while(query_min(1, 1, n, ql, qr) <= 0) update(1, 1, n), mi = INF;
		}
		if(k == 2) updata(1, 1, n, ql, qr, x, 1);
		if(k == 3) updata(1, 1, n, ql, qr, x, 2);
	}
	printf("%d\n", ans);
}

int main(void)
{
	int _;
	while(scanf("%d", &_)!=EOF) {
		while(_--) {
			read();
			work();
		}

	}

	return 0;
}