• SDOI2009 HH的项链


    题目大意

    给定一个序列,求区间出现次数为1次的数字有多少?

    \(n \leq 10^6\)

    思路一

    首先处理出第\(i\)个数上次出现的位置pre,维护一个权值数组表示到第\(i\)个位置时的数字分布情况。

    处理一个区间时就是对于右端点为r时,\(l \leq a[i] \leq r,pre[a[i]] < l\)记录即可

    由于答案具有前缀和性质,用树状数组维护即可。

    代码一

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e6 + 10;
    int pre[N];
    int n;
    int c[N];
    int a[N];
    int l,r;
    int m;
    int ans[N];
    struct node {
    	int id;
    	int pos;
    	node (int _id,int _pos) {
    		id = _id;
    		pos = _pos;
    	}
    };
    
    vector <node> q[N];
    int lowbit(int x) {
    	return x & -x;
    }
    
    void modify(int x,int v) {
    	while(x <= n) {
    		c[x] += v;
    		x += lowbit(x);
    	}
    }
    
    int query(int x) {
    	int ans = 0;
    	while(x) {
    		ans += c[x];
    		x -= lowbit(x);
    	}
    	return ans;
    }
    
    int main () {
    	cin >> n;
    	for(int i = 1;i <= n; i ++) cin >> a[i];
    	cin >> m;
    	for(int i = 1;i <= m; i ++) {
    		cin >> l >> r;
    		q[r].push_back(node(i,l));
    	}
    	for(int i = 1;i <= n; i ++) {
    		if(pre[a[i]]) {
    			modify(pre[a[i]],-1);
    			modify(i,1);
    			pre[a[i]] = i;
    		}
    		else {
    			modify(i,1);
    			pre[a[i]] = i;
    		}
    		for(int j = 0;j < q[i].size(); j ++) {
    			node y = q[i][j];
    			ans[y.id] = query(i) - query(y.pos - 1);
    		}
    	}
    	for(int i = 1;i <= m; i ++) {
    		cout << ans[i] << endl;
    	}
    	return 0;
    }
    

    思路二

    同思路一情况,需维护数组pre,使用主席树在线维护即可。

    代码二

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e6 + 10;
    const int M = (N << 2) + 30;
    
    int rt[M];
    int w[N];
    int last[N];
    struct kcj_seg_tree {
    	int sum[M];
    	int lch[M];
    	int rch[M];
    	int tot = 0;
    	void build(int l,int r,int &root) {
    		root = ++tot;
    		if(l == r) {
    			return;
    		}
    		int mid = (l + r) >> 1;
    		build(l,mid,lch[root]);
    		build(mid + 1,r,rch[root]);
    	}
    	void insert(int l,int r,int &root,int old,int pos) {
    		root = ++tot;
    		lch[root] = lch[old];
    		rch[root] = rch[old];
    		sum[root] = sum[old];
    		if(l == r) {
    			sum[root] ++;
    			return;
    		}
    		int mid = (l + r) >> 1;
    		if(pos <= mid) {
    			insert(l,mid,lch[root],lch[old],pos);
    		}
    		else insert(mid + 1,r,rch[root],rch[old],pos);
    		sum[root] = sum[lch[root]] + sum[rch[root]];
    	}
    
    	int query(int l,int r,int s,int t,int x) {
    		if(l == r) {
    			return sum[t] - sum[s];
    		}
    		int mid = (l + r)  >> 1;
    		int _s = sum[lch[t]] - sum[lch[s]];
    		if(x <= mid) {
    			return query(l,mid,lch[s],lch[t],x);
    		}
    		else {
    			return _s + query(mid + 1,r,rch[s],rch[t],x);
    		}
    	}
    } ST;
    int n,m;
    int main () {
    	scanf("%d",&n);
    	for (int i = 1;i <= n; i ++) {
    		int x;
    		scanf("%d",&x);
    		w[i] = last[x];
    		last[x] = i;
    	}
    	ST.build(1,n,rt[0]);
    	for(int i = 1;i <= n; i ++) {
    		ST.insert(1,n,rt[i],rt[i - 1],w[i] + 1);
    	}
    	scanf("%d",&m);
    	while(m --) {
    		int l,r;
    		scanf("%d %d",&l,&r);
    		int ans = ST.query(1,n,rt[l - 1],rt[r],l);
    		printf("%d\n",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    一文搞定操作系统!超详细图文详解!请带着耐心点进来!
    一文搞定操作系统的进程和线程!
    别再敲代码了,用对工具,做可视化大屏原来这么简单!
    一个网站,让你拥有各类资源!!
    DCN v2
    SSD
    Pytorch 模型的加载与保存
    Pytorch分布式训练
    Pytorch中的BatchNorm
    OHEM(2)
  • 原文地址:https://www.cnblogs.com/Allorkiya/p/15901898.html
Copyright © 2020-2023  润新知