Count The Rectangles

树状数组加上扫描线。
我们可以发现的是夹在平行于x轴的两根线中的所有平行于y轴的竖线,对于答案的统计时nums*(nums-1)/2,故我们可以建立权值树状数组。
枚举两条x的线,然后插入y的线,每一次统计总共有多少根线夹在中间。

    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    //#include
    #include
    #define up(i,a,b)  for(int i=a;i
    #define dw(i,a,b)  for(int i=a;i>b;i--)
    #define upd(i,a,b) for(int i=a;i<=b;i++)
    #define dwd(i,a,b) for(int i=a;i>=b;i--)
    //#define local
    typedef long long ll;
    const double esp = 1e-6;
    const double pi = acos(-1.0);
    const int INF = 0x3f3f3f3f;
    const int inf = 1e9;
    using namespace std;
    int read()
    {
    	char ch = getchar(); int x = 0, f = 1;
    	while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    	while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    	return x * f;
    }
    typedef pair<int, int> pir;
    const int hg = 5001;
    struct node { int a, b, c; };
    bool cmpx(node a, node b) {
    	return a.a < b.a;
    }
    bool cmpy(node a, node b)
    {
    	return a.c < b.c;
    }
    vector<node>x, y;
    ll sum[20000];
    int lowbit(int i)
    {
    	return i & (-i);
    }
    void add(int x, ll val)
    {
    	while (x <= 10005)
    	{
    		sum[x] += val;
    		x += lowbit(x);
    	}
    }
    ll querry(int x)
    {
    	ll res = 0;
    	while (x)
    	{
    		res += sum[x];
    		x -= lowbit(x);
    	}
    	return res;
    }
    int n;
    int main()
    {
    	n = read();
    	int a1, a2, b1, b2;
    	upd(i, 1, n)
    	{
    		a1 = read(), b1 = read(), a2 = read(), b2 = read();
    		if (a1 == a2)
    		{
    			y.push_back(node{ a1+hg,min(b1,b2) + hg,max(b1,b2) + hg });
    		}
    		else
    			x.push_back(node{ b1+hg,min(a1,a2) + hg,max(a1,a2) + hg });
    	}
    	sort(x.begin(), x.end(),cmpx), sort(y.begin(), y.end(),cmpy);
    	ll ans = 0;
    	up(i, 0, x.size())
    	{
    		memset(sum, 0, sizeof(sum));
    		int k = y.size()-1;
    		for (int j = x.size() - 1; x[j].a > x[i].a; j--)
    		{
    			while (k >= 0 && y[k].c >= x[j].a)
    			{
    				if (y[k].b <= x[i].a)
    					add(y[k].a, 1);
    				k--;
    			}
    			int l = max(x[i].b, x[j].b), r = min(x[i].c, x[j].c);
    			if (l > r)continue;
    			ll ret = querry(r) - querry(l - 1);
    			ans += ret * (ret - 1) / 2;
    		}
    	}
    	cout << ans << endl;
    }

你可能感兴趣的:(树状数组,偏序集)