1. 程式人生 > >【BZOJ2762】[JLOI2011]不等式組(樹狀陣列)

【BZOJ2762】[JLOI2011]不等式組(樹狀陣列)

題目:

分析:

加入的不等式分三種情況 當a>0,可以變成x>cbaa=0,若b>c則恆成立,否則恆不成立 當a<0,可以變成x<cba

對於a=0,用一個變數sum記一下當前有多少不等式恆成立,刪除的時候注意要維護sum

對於a0,可以開兩個權值樹狀陣列greaterless記錄。當加入a>0時,令x=cba,給greaterx位置加1,查詢時查

[0,k)區間的和。a<0時在less上類似。

對於刪除操作,在樹狀陣列上刪除該不等式貢獻的值即可。注意要記錄已刪除的不等式防止重複刪除。

程式碼:

這題思路簡單,但是程式碼細節比較多……

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
namespace zyt
{
    const int DELETED = 1e9, P = 1e6
+ 10, OPT = 1e5 + 10, N = P * 2; class Tree_Array { private: int data[N]; inline int lowbit(const int x) { return x & -x; } public: Tree_Array() { memset(data, 0, sizeof(data)); } inline void add(int
a, const int x) { while (a < N) data[a] += x, a += lowbit(a); } inline int query(int a) { int ans = 0; while (a > 0) ans += data[a], a -= lowbit(a); return ans; } }less, greater; int n; pair<int, int> opt[OPT]; int cnt, sum; int work() { ios::sync_with_stdio(false); cin.tie(NULL); cin >> n; for (int i = 0; i < n; i++) { string s; cin >> s; if (s == "Add") { int a, b, c, x; cin >> a >> b >> c; if (a == 0) { opt[++cnt] = make_pair(0, (bool)(b > c)); if (b > c) sum++; } else if (a < 0) { x = (int)(ceil((c - b) / (double)a) + P); if (x < 1) x = 1; if (x >= N) x = N - 1; opt[++cnt] = make_pair(-1, x); less.add(x, 1); } else { x = (int)(floor((c - b) / (double)a) + P); if (x < 1) x = 1; if (x >= N) x = N - 1; opt[++cnt] = make_pair(1, x); greater.add(x, 1); } } else if (s == "Del") { int a; cin >> a; if (opt[a].first == 0) sum -= (opt[a].second == 1); else if (opt[a].second != DELETED) { if (opt[a].first == -1) less.add(opt[a].second, -1); else greater.add(opt[a].second, -1); } opt[a].second = DELETED; } else { int a; cin >> a; a += P; cout << sum + greater.query(a - 1) + less.query(N - 1) - less.query(a) << '\n'; } } return 0; } } int main() { return zyt::work(); }