解题思路:
两棵bit分别存线段的开始点和结束点
两个数组存开始点和结束点的线段数量
针对每次询问
用总线段数 - 区间右边的线段(结尾小于等于x) - 区间左边的线段(开头大于等于x) - 当前线段内被完全包含 - 开头结尾在当前区间内即为答案
在线更新询问 复杂度Onlogn
/*
Zeolim - An AC a day keeps the bug away
*/
//#pragma GCC optimize(2)
//#pragma GCC ("-W1,--stack=128000000")
#include <bits/stdc++.h>
using namespace std;
#define mp(x, y) make_pair(x, y)
#define fr(x, y, z) for(int x = y; x < z; ++x)
#define fi(x, n) fill(x, x + n + 10, 0)
typedef long long ll;
typedef unsigned long long ull;
typedef double ld;
typedef std::pair <int, int> pii;
typedef std::vector <int> vi;
//typedef __int128 ill;
const ld PI = acos(-1.0);
const ld E = exp(1.0);
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MOD = 386910137;
const ull P = 13331;
const int MAXN = 1e5 + 100;
struct bit
{
ll c[MAXN], N; //c?, N???
bit() {}
bit(int n) { N = n; fill(c, c + N + 1, 0); }
int lowbit(int x) { return x & -x; }
void update(int pos, ll val)
{
for( ;pos <= N; pos += lowbit(pos))
c[pos] += val;
}
ll ask(int pos)
{
ll ret = 0;
for( ;pos; pos -= lowbit(pos))
ret += c[pos];
return ret;
}
};
int t[MAXN], t1[MAXN], t2[MAXN];
int b[MAXN], e[MAXN];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
//freopen("sgtck.out","w",stdout);
//freopen("sgt.in","r",stdin);
int n, q, sum, cntsum;
while( cin >> n >> q )
{
sum = 0;
fi(t, n); fi(t1, n); fi(t2, n);
fi(b, n); fi(e, n);
bit fst(n + 10), lst(n + 10);
int x, y;
while(q--)
{
int opt;
cin >> opt;
if(opt == 1)
{
cin >> x >> y;
++sum;
fst.update(x, 1);
lst.update(y, 1);
if(x == y)
++t[x];
else
++b[x], ++e[y];
}
else
{
cin >> x >> y;
int ans = sum;
if(x == y)
{
ans -= lst.ask(x - 1);
ans -= (fst.ask(n) - fst.ask(y));
}
else if(x + 1 == y)
{
ans -= lst.ask(x);
ans -= (fst.ask(n) - fst.ask(y - 1));
}
else
{
ans -= lst.ask(x);
ans -= (fst.ask(n) - fst.ask(y - 1));
ans -= t[x + 1];
ans -= b[x + 1];
ans -= e[x + 1];
}
cout << ans << '
';
}
}
}
return 0;
}
/*
5 9
1 1 3
1 2 4
1 3 5
1 2 2
1 3 3
1 4 4
1 3 4
1 4 5
2 3 3
*/