其他分享
首页 > 其他分享> > luoguP1972 [SDOI2009]HH的项链

luoguP1972 [SDOI2009]HH的项链

作者:互联网

题意

求一段区间中的元素种类, 同一个元素可能有多个,但是只记
一次, 多组询问
长度 <= 1000000, 询问次数 <= 200000

记得写快读

分析

重复颜色, 套路题

处理nxt

具体做法来自: 150137

没有修改,我们不妨离线
我们将询问按照左端点排序, 然后维护一个当前的左指针和询问的左指针, 再维护一个 next 数组表示该物品的下一个相同元素物品的位置
维护一个 ans 数组, 每次当 l < ql 的时候, 更新 nextl, 然后 l 前
移继续即可,询问就是求前缀和啦

记得离散化(以后能离散化就离吧,不耽误)

#include<cstdio>
#include<algorithm>
using namespace std;
#define lowbit(x) (x&-x)
inline int read() {
    char ch = getchar(); int f = 1, x = 0;
    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;
}
const int MAX = 1000000+99;

int n, m;
struct node2{
    int arr, x, ID;
}a[MAX];
bool cmp3(node2 a, node2 bb) { return a.arr < bb.arr; }
bool cmp4(node2 a, node2 bb) { return a.ID < bb.ID; }

int nxt[MAX], lst[MAX];
int t[MAX];
struct node{
    int l, r;
    int ans, id;
}cmd[MAX];
bool cmp1(node a, node bb) { return a.l < bb.l; }
bool cmp2(node a, node bb) { return a.id < bb.id; }
 
void add(int x, int k) {
    while(x <= n) {t[x] += k; x += lowbit(x);} 
}
int query(int x) {
    int res = 0;
    while(x) {res += t[x]; x -= lowbit(x);}
    return res;
}
void pre() {
    n = read();
    for(int i = 1; i <= n; i++) a[i].arr = read(), a[i].ID = i;
    
    sort(a+1, a+1+n, cmp3);
    int tot = 1;//离散化
    a[1].x = 1;
    for(int i = 2; i <= n; i++) {
        if(a[i].arr != a[i-1].arr) ++tot;
        a[i].x = tot;
    }
    sort(a+1, a+1+n, cmp4);
    
    for(int i = n; i >= 1; i--) {//颜色问题--处理nxt[]
        nxt[i] = lst[a[i].x];
        lst[a[i].x] = i;
    }
    for(int i = 1; i <= n; i++) if(lst[i]) add(lst[i], 1);//初始化l=1的状态(注意判颜色是否存在
    m = read();
    for(int i = 1; i <= m; i++) cmd[i].id = i,cmd[i].l = read(), cmd[i].r = read();
    sort(cmd+1, cmd+1+m, cmp1);//按 l 从小到大排序 
}

void solve() {
    int pos = 1;
    for(int l = 1; l <= n; l++) {//枚举左端点 
        while(l == cmd[pos].l) {
            cmd[pos].ans = query(cmd[pos].r) - query(cmd[pos].l-1);//l 前面的没用了,直接减掉 
            ++pos;
        }
        if(nxt[l]) add(nxt[l], 1);
    }
    
    sort(cmd+1, cmd+1+m, cmp2);
    for(int i = 1; i <= m; i++) printf("%d\n", cmd[i].ans);
}

int main() {
//  freopen("2.in", "r", stdin);
//  freopen("2.out", "w", stdout);
    pre();
    solve();    
    return 0;
}

标签:nxt,ch,int,询问,while,HH,SDOI2009,include,luoguP1972
来源: https://www.cnblogs.com/tyner/p/11616770.html