set维护连续段+线段树:1018T2

本文搬运自本人高中时期CSDN博客,若图片加载不出来,可到原文查看:https://blog.csdn.net/zhangtingxiqwq/article/details/133914164

http://cplusoj.com/d/senior/p/386?tid=652f5fe6c1fe41bc229c18fb

线段树维护01,和,支持翻转操作

用类似珂朵莉树的方法维护连续段,连续段之间分别统计,取max

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar(); while(ch<'0'||
ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back
//mt19937 rand(time(0));
//mt19937_64 rand(time(0));
//srand(time(0));
#define N 1500010
//#define M
//#define mo
struct Ment {
int l, r;
bool operator < (const Ment &A) const {
return l < A.l;
}
};
struct ANS {
int x, y;
void operator += (const ANS &A) {
x += max(A.x, A.y);
y += min(A.x, A.y);
}
void operator -= (const ANS &A) {
x -= max(A.x, A.y);
y -= min(A.x, A.y);
}
ANS operator + (const ANS &A) const {
ANS B;
B.x = x + A.x;
B.y = y + A.y;
return B;
}
}ans;
struct QRY {
int l, r, d;
}qry[N];
int n, m, i, j, k, T;
int l, r, len, mn, mx, rt, v[N];
set<Ment>s;
set<Ment>::iterator it, it1, it2;

struct Segment_tree {
int tot, ls[N<<2], rs[N<<2];
int s[N<<2][2], c[N<<2][2], tag[N<<2];
void push_up(int k) {
s[k][0]=s[ls[k]][0]+s[rs[k]][0];
s[k][1]=s[ls[k]][1]+s[rs[k]][1];
c[k][0]=c[ls[k]][0]+c[rs[k]][0];
c[k][1]=c[ls[k]][1]+c[rs[k]][1];
}
void print(int k, int l, int r) {
printf("# %d : [%d %d]\n", k, l, r);
printf("s : %lld %lld\n", s[k][0], s[k][1]);
printf("c : %lld %lld\n", c[k][0], c[k][1]);
}
void build(int &k, int l, int r) {
if(!k) k=++tot;
if(l==r) {
int len=v[l+1]-v[l]; // [v(l), v(l+1)-1]
if(v[l+1]%2==0) c[k][0]=(len+1)/2, c[k][1]=len/2;
else c[k][1]=(len+1)/2, c[k][0]=len/2;
return ;
}
int mid = (l+r)>>1;
build(ls[k], l, mid);
build(rs[k], mid+1, r);
push_up(k);
// print(k, l, r);
}
void modify(int k, int h) { //k节点加上h
tag[k]+=h;
s[k][0]+=(c[k][0]+c[k][1])*(h/2);
s[k][1]+=(c[k][0]+c[k][1])*(h/2);
if(h % 2 == 0) return ;
swap(c[k][0], c[k][1]);
s[k][0]+=c[k][0]; s[k][1]+=c[k][1];
}
void push_down(int k) {
modify(ls[k], tag[k]);
modify(rs[k], tag[k]);
tag[k]=0;
}
void add(int k, int l, int r, int x, int y, int h) {
if(l>=x && r<=y) return modify(k, h), void();
int mid = (l+r)>>1; push_down(k);
if(x <= mid) add(ls[k], l, mid, x, y, h);
if(y >= mid+1) add(rs[k], mid+1, r, x, y, h);
push_up(k);
}
ANS que(int k, int l, int r, int x, int y) {
if(l>=x && r<=y) return {s[k][0], s[k][1]};
int mid = (l+r)>>1; push_down(k);
ANS A, B; A.x=A.y=B.x=B.y=0;
if(x <= mid) A = que(ls[k], l, mid, x, y);
if(y >= mid+1) B = que(rs[k], mid+1, r, x, y);
push_up(k);
return A + B;
}
}Seg;

signed main()
{
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
freopen("nvwa.in", "r", stdin);
freopen("nvwa.out", "w", stdout);
// T=read();
// while(T--) {
//
// }
auto Add = [&] (int x) -> void {
v[++j]=x;
if(x-2>=1) v[++j]=x-2;
if(x-1>=1) v[++j]=x-1;
if(x+1<=n) v[++j]=x+1;
if(x+2<=n) v[++j]=x+2;
// if(x+3<=n) v[++j]=x+3;
};
n=read()+10; T=read();
v[++j]=1; v[++j]=n;
for(i=1; i<=T; ++i) {
qry[i].l=read()+1+1+1; qry[i].r=read()+1+1; qry[i].d=read();
Add(qry[i].l); Add(qry[i].r);
}
sort(v+1, v+j+1);
len = unique(v+1, v+j+1) - v - 1; v[len+1]=n+1;
// for(i=1; i<=len+1; ++i) printf("%lld ", v[i]); printf("\n");
Seg.build(rt, 1, len);
for(i=1; i<=len; ++i) s.insert({i, i});
for(i=1; i<=T; ++i) {
l = qry[i].l; r = qry[i].r;
l = lower_bound(v+1, v+len+1, l) - v;
r = lower_bound(v+1, v+len+1, r) - v;
// printf(">> %lld %lld\n", l, r);
it1 = s.lower_bound({l, 0}); --it1;
it2 = s.lower_bound({r+1, 0});
mn = 1e9; mx = -1e9;
// printf("> %lld %lld\n", ans.y, ans.x);
for(it = it1; it != it2; ++it) {
mn = min(mn, (it->l));
mx = max(mx, (it->r));
ans -= Seg.que(1, 1, len, (it->l), (it->r));
// printf("Del : [%lld %lld] => %lld %lld\n", (it->l), (it->r), ans.y, ans.x);
}
s.erase(it1, it2); s.insert({mn, mx});
//// printf(">> [%lld %lld]\n", mn, mx);
Seg.add(1, 1, len, l, r, qry[i].d);
ans += Seg.que(1, 1, len, mn, mx);
printf("%lld %lld\n", ans.y, ans.x);
//// for(auto t : s) printf("[%lld %lld] ", t.l, t.r);
// printf("\n");
}
return 0;
}