• 【BZOJ2762】[JLOI2011]不等式组(树状数组)


    题目:

    BZOJ2762

    分析:

    加入的不等式分三种情况
    (a>0),可以变成(x>lfloor frac{c-b}{a} floor)
    (a=0),若(b>c)则恒成立,否则恒不成立
    (a<0),可以变成(x<lceil frac{c-b}{a} ceil)

    对于(a=0),用一个变量(sum)记一下当前有多少不等式恒成立,删除的时候注意要维护(sum)

    对于(a eq0),可以开两个权值树状数组(greater)(less)记录。当加入(a>0)时,令(x=lfloor frac{c-b}{a} floor),给(greater)(x)位置加(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) << '
    ';
    			}
    		}
    		return 0;
    	}
    }
    int main()
    {
    	return zyt::work();
    }
    
  • 相关阅读:
    [剑指 Offer 11. 旋转数组的最小数字]
    进程描述符(PCB)
    [剑指 Offer 57. 和为s的两个数字]
    Linux netstat命令
    kafka2.3.X配置文件
    docker
    shell操作mysql数据库
    Linux文件查找之find命令
    sed 切割日志文件
    Linux文本处理之awk
  • 原文地址:https://www.cnblogs.com/zyt1253679098/p/9694972.html
Copyright © 2020-2023  润新知