[YNOI 2016] 掉进兔子洞

[题目链接]

         https://www.lydsy.com/JudgeOnline/problem.php?id=4939

[算法]

         不难发现 , 

         ansi = (r1 - l1 + 1) + (r2 - l2 + 1) + (r3 - l3 + 1) - sigma(min(cnt1i , cnt2i , cnt3i))

         bitset + 莫队即可

         时间复杂度 : O(Nsqrt(N) / 32)

[代码]

       

#include<bits/stdc++.h>
using namespace std;
#define N 100010
#define TT 25000
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

struct query
{
    int l , r;
    int id; 
} q[N];

int n , m , sz;
int cnt[N] , block[N] , ans[N] , l1[N] , r1[N] , l2[N] , r2[N] , l3[N] , r3[N] , a[N] , b[N];
bool vis[N];
bitset< N > tmp , f[TT + 5];

template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
template <typename T> inline void read(T &x)
{
   T f = 1; x = 0;
   char c = getchar();
   for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
   for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
   x *= f;
}
inline void add(int x)
{
    tmp[a[x] + cnt[a[x]]] = 1;
    ++cnt[a[x]];
}
inline void dec(int x)
{
    tmp[a[x] + cnt[a[x]] - 1] = 0;
    --cnt[a[x]];
}
inline bool cmp(query a , query b)
{
    if (block[a.l] == block[b.l]) return a.r < b.r;
    else return a.l < b.l;
}
inline void solve(int l , int r)
{
    tmp.reset();
    memset(cnt , 0 , sizeof(cnt));
    memset(vis , false , sizeof(vis));
    int len = 0;
    for (int i = 1; i <= TT; i++) f[i].reset();
    for (int i = l; i <= r; i++)
    {
        q[++len] = (query){l1[i] , r1[i] , i};
        ans[i] += r1[i] - l1[i] + 1;
        q[++len] = (query){l2[i] , r2[i] , i};
        ans[i] += r2[i] - l2[i] + 1;
        q[++len] = (query){l3[i] , r3[i] , i};
        ans[i] += r3[i] - l3[i] + 1;
    }    
    sort(q + 1 , q + len +  1, cmp);
    int L = q[1].l , R = q[1].l - 1;
    for (int i = 1; i <= len; i++)
    {
        while (R < q[i].r)
        {
            add(R + 1);
            ++R;
        }
        while (R > q[i].r)
        {
            dec(R);
            --R;
        }
        while (L < q[i].l)
        {
            dec(L);
            ++L;
        }
        while (L > q[i].l)
        {
            add(L - 1);
            --L;
        }
        if (!vis[q[i].id - l + 1]) 
        {
            vis[q[i].id - l + 1] = true;
            f[q[i].id - l + 1] = tmp;
        } else f[q[i].id - l + 1] &= tmp;
    }
    for (int i = l; i <= r; i++)
        ans[i] -= f[i - l + 1].count() * 3;
}

int main()
{
    
    read(n); read(m);
    int size = (int)sqrt(n) + 1;
    for (int i = 1; i <= n; i++) block[i] = (i - 1) / size + 1;
    for (int i = 1; i <= n; i++) 
    {
        read(a[i]);
        b[i] = a[i];
    }
    sort(b + 1 , b + n + 1);
    for (int i = 1; i <= n; i++) a[i] = lower_bound(b + 1 , b + n + 1 , a[i]) - b;
    for (int i = 1; i <= m; i++)
    {
        read(l1[i]); read(r1[i]);
        read(l2[i]); read(r2[i]);
        read(l3[i]); read(r3[i]);

    }
    for (int i = 1; i <= m; i += TT) solve(i , min(i + TT - 1 , m));
    for (int i = 1; i <= m; i++) printf("%d\n" , ans[i]);
    
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/evenbao/p/10372211.html