牛客网多校第5场 I vcd 【树状数组+离散化处理】【非原创】

题目:戳这里

学习博客:戳这里

作者:阿狸是狐狸啦

 

n个点,一个点集S是好的,当且仅当对于他的每个子集T,存在一个右边无限延长的矩形,使的这个矩形包含了T,但是和S-T没有交集。

求有多少个这种集合。

画图找规律可得

当我们求的集合中的点只有一个时,肯定满足要求 。

当有两个点且这两个点y坐标不相等也满足要求。

当有三个点组成一个小于号形状的集合S时,这个集合S的子集T一定与S-T无交集,当组成一个大于号时。我们取大于号左边的两个端点组成的T集合一定与右边的那个端点有交集。

当有四个点组成的S点集他一定存在一个子集T和S-T有交集。

所以我们计算小于等于三个点的情况就行了。

一的情况直接是n。

二的情况总的情况减去y坐标相等的点的情况就行了。

三的情况就是数一下有多少个小于号的情况,树状数组维护一下就行了。

 

附ac代码:

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <queue>
  5 #include <stack>
  6 #include <iostream>
  7 using namespace std;
  8 typedef long long ll;
  9 const int maxn = 2 * 1e5 + 10;
 10 const ll mod =  998244353;
 11 struct nod
 12 {
 13     ll x;
 14     ll y;
 15 }coo[maxn];
 16 ll cnt[maxn];
 17 ll c[maxn<<2];
 18 ll y[maxn];
 19 ll n;
 20 bool cmp(nod a, nod b)
 21 {
 22     return a.x > b.x;
 23 }
 24 ll pmul(ll a, ll b)
 25 {
 26     ll res = 0;
 27     while(b)
 28     {
 29         if(b&1)
 30             res = (res + a) % mod;
 31         b >>= 1;
 32         a = (a + a) % mod;
 33     }
 34     return res;
 35 }
 36 ll pmod(ll a, ll b)
 37 {
 38     ll res = 1;
 39     while(b)
 40     {
 41         if(b&1)
 42             res = pmul(res, a) % mod;
 43         b >>= 1;
 44         a = pmul(a, a) % mod;
 45     }
 46     return res;
 47 }
 48 ll gets(int x)
 49 {
 50     ll ans = 0;
 51     while(x)
 52     {
 53         ans = (ans + c[x]) % mod;
 54         x -= x & (-x);
 55     }
 56     return ans;
 57 }
 58 void updat(int x, ll ad)
 59 {
 60     while(x <= n)
 61     {
 62         c[x] = (c[x] + ad) % mod;
 63         x += x & (-x);
 64     }
 65 }
 66 int main() {
 67  
 68     scanf("%d", &n);
 69     for(ll i = 1; i <= n; ++i)
 70     {
 71         scanf("%d %d", &coo[i].x, &coo[i].y);
 72         y[i] = coo[i].y;
 73     }
 74     sort(y + 1, y + 1 + n);
 75     for(ll i = 1; i <= n; ++i)//这一步很有意思,把1e9的范围离散化到了1e5
 76     {
 77         ll u = lower_bound(y + 1, y + 1 + n, coo[i].y) - y;
 78         coo[i].y = u;
 79         ++cnt[u];
 80        // printf("%d u\n", u);
 81     }
 82     sort(coo + 1, coo + 1 + n, cmp);
 83     ll ans = n + n * (n - 1) / 2;
 84     ans %= mod;
 85     for(ll i = 1; i <= n; ++i)
 86     {
 87         ll u = cnt[i];
 88         if(u)
 89         ans = (ans - u * (u - 1) / 2) % mod;
 90     }
 91     ll up = 0, dw = 0;
 92     ll now = 1;
 93     for(ll i = 1; i <= n; ++i)
 94     {
 95         up = (gets(n) - gets(coo[i].y)) % mod;
 96         dw = gets(coo[i].y - 1) % mod;
 97         ans = (ans + up * dw % mod) % mod;
 98         for(;coo[i].x != coo[i + 1].x && now <= i; ++now)
 99         {
100             updat(coo[now].y, 1ll);
101         }
102     }
103     printf("%lld\n", ans % mod);
104     return 0;
105 }
View Code

 

posted @ 2018-08-19 01:09  euzmin  阅读(157)  评论(0编辑  收藏  举报