• BZOJ 1878 [SDOI2009]HH的项链 (主席树 或 莫队算法)


    题目链接  HH的项链

    这道题可以直接上主席树的模板

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)    for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)    for (int i(a); i >= (b); --i)
    
    typedef long long LL;
    
    const int N = 5e4 + 10;
    const int M = 3e6 + 10;
    
    int n, tot, q, a[N];
    int T[M], lson[M], rson[M], val[M];
    int nxt[N], b[N];
    int m;
    
    int build(int l, int r){
    	int rt = tot++;  
    	val[rt] = 0;  
    	int m = (l + r) >> 1;  
    	if(l != r){  
    		lson[rt] = build(l, m);  
    		rson[rt] = build(m + 1, r);  
    	}  
    	return rt;  
    }  
    int update(int rt, int pos, int v){  
    	int newrt = tot++, tmp = newrt;
    	int l = 1, r = n;
    	val[newrt] = val[rt] + v;
    	while(l < r)
    	{
    		int m = (l + r) >> 1;
    		if(pos <= m)
    		{
    			lson[newrt] = tot++;
    			rson[newrt] = rson[rt];
    			newrt = lson[newrt];
    			rt = lson[rt];
    			r = m;
    		}
    		else
    		{
    			rson[newrt] = tot++;
    			lson[newrt] = lson[rt];
    			newrt = rson[newrt];
    			rt = rson[rt];
    			l = m + 1;
    		}
    		val[newrt] = val[rt] + v;
    	}
    	return tmp;
    }
    
    int query(int rt, int pos){
    	int ret = 0;
    	int l = 1, r = n;
    	while(pos > l){
    		int m = (l + r) >> 1;
    		if (pos <= m){
    			ret += val[rson[rt]];
    			rt = lson[rt];
    			r = m;
    		}
    		else{  
    			l = m + 1;
    			rt = rson[rt];
    		}
    	}
    	return ret + val[rt];
    }
    
    int ask(int l, int r){ return query(T[r], l); }
    
    void init(){
    	tot = 0;
    	memset(nxt, -1, sizeof(nxt));  
    	rep(i, 1, n) b[i - 1] = a[i];
    	sort(b, b + n);
    	int cnt = unique(b, b + n) - b;
    	T[0] = build(1, n);
    	rep(i, 1, n){
    		int id = lower_bound(b, b + cnt, a[i]) - b;
    		if(nxt[id] == -1)
    			T[i] = update(T[i - 1], i, 1);
    		else{
    			int t = update(T[i - 1], nxt[id], -1);
    			T[i] = update(t, i, 1);
    		}
    		nxt[id] = i;
    	}
    }
    
    int main(){
    
    	scanf("%d", &n);
    	rep(i, 1, n) scanf("%d", a + i);
    
    	init();
    	scanf("%d", &m);
    	while (m--){
    		int x, y;
    		scanf("%d%d", &x, &y);
    		printf("%d
    ", ask(x, y));
    	}
    
    	return 0;
    
    }  
    

    当然用莫队算法也是可以做的

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    
    typedef long long LL;
    
    const int N = 2e5 + 10;
    
    int belong[N];
    int a[N], b[N], c[N], ans[N];
    int n, m, l, r, cnt, BS;
    int now = 0;
    
    struct node{
    	int l, r, id;
    	friend bool operator < (const node &a, const node &b){
    		return belong[a.l] == belong[b.l] ? belong[a.r] < belong[b.r] : belong[a.l] < belong[b.l];
    	}
    } q[N];
    
    int main(){
    
    	scanf("%d", &n);
    	BS = (int)sqrt(n + 0.5);
    
    
    	rep(i, 1, n) scanf("%d", a + i), b[i] = a[i];
    	sort(b + 1, b + n + 1);
    	cnt = unique(b + 1, b + n + 1) - b - 1;
    	rep(i, 1, n) a[i] = lower_bound(b + 1, b + cnt + 1, a[i]) - b;
    
    	scanf("%d", &m);
    	rep(i, 1, m){
    		scanf("%d%d", &q[i].l, &q[i].r);
    		q[i].id = i;
    	}
    
    	rep(i, 1, n) belong[i] = (i - 1) / BS + 1;
    	sort(q + 1, q + m + 1);
    
    	l = 0, r = 0;
    	rep(i, 1, m){
    		while (l > q[i].l){ --l; if (c[a[l]] == 0) ++now; ++c[a[l]]; }
    		while (r < q[i].r){ ++r; if (c[a[r]] == 0) ++now; ++c[a[r]]; }
    
    		while (l < q[i].l){ --c[a[l]]; if (!c[a[l]]) --now; ++l; }
    		while (r > q[i].r){ --c[a[r]]; if (!c[a[r]]) --now; --r; }
    
    		ans[q[i].id] = now;
    	}		
    
    	rep(i, 1, m) printf("%d
    ", ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    Android开发之记账本开发第四天
    动手动脑——继承与多态
    跟踪某个类所创建对象的个数
    动手动脑——类与对象
    石家庄地铁模拟
    动手动脑——方法
    查询单词出现次数
    动手动脑——JAVA语法基础
    原码反码补码
    ATM机模拟系统
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/7467268.html
Copyright © 2020-2023  润新知