zoukankan      html  css  js  c++  java
  • SDOI2009 HH的项链

    传送门

    这道题原来是可以用莫队暴力过掉的……但是数据加强之后500000万的范围使得nsqrtn的算法无法通过,那我们只能用log的方法,也就是树状数组。

    本题要求我们统计的是贝壳的个数,我们唯一的困难在于如何判断重复元素。考虑这样一个事情,对于一些右端点相同的区间,我们在统计这些区间之内的情况的时候,重复的元素我们只关心它出现在最右边的一个。

    举例子,比如区间1,2,3,2,4 对于这个长度为5的区间,我们对于每个诸如[l,5]的询问,第一个2完全不需要被考虑,因为它已经被第二个2完全覆盖了。(左端点靠前的,2可以被后面的计算,靠后的就完全没前面事了

    所以我们可以把所有的区间按右端点排序,之后离线处理。对于每个右端点,把在其之前的都在树状数组中加上,而已经出现过的元素,就在原来的位置先删除,之后再在当前位置添加。统计的时候直接计算两端和相减即可。

    听起来是不是很简单……?

    看一下代码。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    const int M = 1005;
    const int N = 1000005;
    const int INF = 1e9;
    double eps = 1e-7;
    typedef long long ll;
    
    int read()
    {
        int ans = 0,op = 1;
        char ch = getchar();
        while(ch < '0' || ch > '9')
        {
            if(ch == '-') op = -1;
            ch = getchar();
        }
        while(ch >= '0' && ch <= '9')
        {
            ans *= 10;
            ans += ch - '0';
            ch = getchar();
        }
        return ans * op;
    }
    
    struct ask
    {
        int l,r,pos;
        bool operator < (const ask &g) const
        {
            if(r == g.r) return l < g.l;
            return r < g.r;
        }
    }a[N];
    struct answer
    {
        int val,p;
        bool operator < (const answer &g) const
        {
            return p < g.p;
        }
    }ans[N];
    int n,m,shell[N],cur = 1,c[N],loc[N];
    bool vis[N];
    int lowbit(int x)
    {
        return x & (-x);
    }
    void add(int x,int v)
    {
        while(x <= n)
        {    
            c[x] += v;
            x += lowbit(x);
        }
    }
    int query(int x)
    {
        int sum = 0;
        while(x)
        {
            sum += c[x];
            x -= lowbit(x);
        }
        return sum;
    }
    int main()
    {
        n = read();
        rep(i,1,n) shell[i] = read();
        m = read();
        rep(i,1,m) a[i].l = read(),a[i].r = read(),a[i].pos = i;
        sort(a+1,a+1+m);
        rep(i,1,m)
        {
            while(cur <= a[i].r)//所有在前面的都要统计
            {
                if(!vis[shell[cur]]) add(cur,1),loc[shell[cur]] = cur,vis[shell[cur]] = 1;//这个元素没出现过
                else add(loc[shell[cur]],-1),add(cur,1),loc[shell[cur]] = cur;//元素出现过
                cur++;
            }
            ans[i].val = query(a[i].r) - query(a[i].l-1),ans[i].p = a[i].pos;//计算出现次数
        }
        sort(ans+1,ans+1+m);//注意要重新按照出现的次序排序
        rep(i,1,m) printf("%d
    ",ans[i].val);
        return 0;
    }
  • 相关阅读:
    Mysql 索引原理《一》索引原理与慢查询2
    Mysql 索引原理《一》索引原理与慢查询1
    Mysql内置功能《六》流程控制
    Mysql内置功能《五》 函数
    Mysql内置功能《四》存储过程
    Mysql pymysql模块
    HDU2020 绝对值排序
    HDU2019 数列有序
    HDU2018 母牛的故事
    HDU2016 数据的交换输出
  • 原文地址:https://www.cnblogs.com/captain1/p/9571899.html
Copyright © 2011-2022 走看看