P6514 [QkOI#R1] Quark and Strings

(7 mins to read)

要求维护n个字符串,每次在区间[l,r]加一个字符,或询问区间[l,r]的字符串的最长公共子序列的长度

做法

本质就是每次插入一条[l,r]的线段,或询问左端点<=l&&右端点>=r的线段的个数,转化后就是一个二维数点的模型,cdq分治,树套树,kdt都可以解决

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
#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) begin(x), end(x)
#define fi first
#define se second
#define debug(x) cerr << #x << " " << x << '\n'
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pli = pair<ll,int>;
const int INF = 0x3f3f3f3f, N = 1e5 + 5;
const ll LINF = 1e18 + 5;
constexpr int k = 2;
constexpr double alpha = 0.75;
const int MAXSIZE = 1 << 20;
char buf[MAXSIZE], *p1, *p2;
inline char gc()
{
return (p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXSIZE,stdin),p1==p2) ? EOF : *p1++);
}
template <class T>
inline void read(T& t)
{
t = 0; int f = 1;
char c = gc();
while(c>'9'||c<'0') {if(c=='-') f = -f; c = gc();}
while(c>='0'&&c<='9') t = t*10 + c - 48, c = gc();
t *= f;
}
int D, pool[N], top, tot, rt;
struct point
{
int x[k];
bool operator < (const point &oth) const {
return x[D] < oth.x[D];
}
}a[N], cur;
struct node
{
int mx[k], mn[k];
int l, r, sz;
point tp;
}t[N];
int newnode()
{
if(top) return pool[top--];
return ++tot;
}
void pushup(int p)
{
int l = t[p].l, r = t[p].r;
for(int i=0; i<k; i++)
{
t[p].mn[i] = t[p].mx[i] = t[p].tp.x[i];
if(l) t[p].mn[i] = min(t[p].mn[i], t[l].mn[i]), t[p].mx[i] = max(t[p].mx[i], t[l].mx[i]);
if(r) t[p].mn[i] = min(t[p].mn[i], t[r].mn[i]), t[p].mx[i] = max(t[p].mx[i], t[r].mx[i]);
}
t[p].sz = t[l].sz + t[r].sz + 1;
}
int build(int l, int r, int d)
{
if(l>r) return 0;
int p = newnode(), mid = (l+r)>>1;
D = d;
nth_element(a+l, a+mid, a+r+1);
t[p].tp = a[mid];
t[p].l = build(l, mid-1, d^1);
t[p].r = build(mid+1, r, d^1);
pushup(p);
return p;
}
void rebuild(int p, int num)
{
if(t[p].l) rebuild(t[p].l, num);
a[num+t[t[p].l].sz+1] = t[p].tp, pool[++top] = p;
if(t[p].r) rebuild(t[p].r, num+t[t[p].l].sz+1);
}
void test(int &p, int d)
{
if(alpha*t[p].sz<t[t[p].l].sz||alpha*t[p].sz<t[t[p].r].sz)
rebuild(p, 0), p = build(1, t[p].sz, d);
}
void insert(int &p, int d)
{
if(!p)
{
p = newnode();
t[p].tp = cur;
t[p].l = t[p].r = 0;
pushup(p);
return;
}
if(cur.x[d]>t[p].tp.x[d]) insert(t[p].r, d^1);
else insert(t[p].l, d^1);
pushup(p); test(p, d);
}
int ask(int p)
{
if(!p) return 0;
if(t[p].mx[0]<=cur.x[0]&&t[p].mn[1]>=cur.x[1]) return t[p].sz;
if(t[p].mn[0]>cur.x[0]||t[p].mx[1]<cur.x[1]) return 0;
int ans = 0;
if(t[p].tp.x[0]<=cur.x[0]&&t[p].tp.x[1]>=cur.x[1]) ++ans;
ans += ask(t[p].l) + ask(t[p].r);
return ans;
}
int main()
{
int n, q;
read(n); read(q);
for(int i=1; i<=q; i++)
{
int op;
read(op); read(cur.x[0]); read(cur.x[1]);
if(op==1) insert(rt, 0);
else printf("%d\n", ask(rt));
}
return 0;
}