zoukankan      html  css  js  c++  java
  • [CF1000F]One Occurrence 题解

    一句话题意:给定一个数列,每次询问一段区间内有没有只出现一次的数,如果有随便输出一个,否则输出0.

    维护last[i],就是前一个a[i]的位置. 如果是第一个出现,last[i] = 0.
    然后对于每一个数,类似于HH的项链一题的做法,将i位置改成last[i], last[i]位置改成inf。这样区间查询的最小值只要<l就有。
    搞一颗单点修改区间查询的线段树就可以了。

    #include <bits/stdc++.h>
    #define ls(p) (p<<1)
    #define rs(p) (p<<1|1)
    #define fi first
    #define se second
    using namespace std;
    const int N = 500000 + 5;
    const int inf = 0x3f3f3f3f;
    int n, m;
    vector <pair<int , int> > q[N];
    int pre[N], tmp[N], a[N];
    int mn[N<<2], mnp[N<<2], ans[N<<2];
    void Pushup(int p) {
    	if(mn[ls(p)] < mn[rs(p)]) {mn[p] = mn[ls(p)]; mnp[p] = mnp[ls(p)];}
    	else {mn[p] = mn[rs(p)]; mnp[p] = mnp[rs(p)];}
    }
    void Build(int p, int l, int r) {
    	if(l == r) {
    		mn[p] = inf;
    		mnp[p] = a[l];
    		return ;
    	}
    	int mid = (l + r) >> 1;
    	Build(ls(p), l, mid);
    	Build(rs(p), mid + 1, r);
    	Pushup(p);
    }
    void Update(int p, int x, int y, int l, int r) {
    	if(l == r) {
    		mn[p] = y;
    		return;
    	}
    	if(x < l || x > r) return ;
    	int mid = (l + r) >> 1;
    	if(x <= mid) Update(ls(p), x, y, l, mid);
    	else Update(rs(p), x, y, mid + 1, r);
    	Pushup(p);
    }
    
    pair<int, int> Query(int p, int ql, int qr, int l, int r) {
    	if(ql <= l && r <= qr) return {mn[p], mnp[p]};
    	int mid = (l + r) >> 1; pair <int, int> ret = {inf, 0};
    	if(ql <= mid) ret = min(ret, Query(ls(p), ql, qr, l, mid));
    	if(qr > mid) ret = min(ret, Query(rs(p), ql, qr, mid + 1, r));
    	return ret;
    }
    int main() {
    	scanf("%d", &n);
    	for(int i = 1; i <= n; i++) scanf("%d", &a[i]), pre[i] = tmp[a[i]], tmp[a[i]] = i;
    	//for(int i = 1; i <= n; i++) cout << pre[i] << " ";
    	//cout <<endl;
    	scanf("%d", &m);
    	for(int i = 1; i <= m; i++) {
    		int l, r; scanf("%d%d", &l, &r);
    		q[r].push_back({l, i});
    	}
    
    	Build(1, 1, n);
    	for(int i = 1; i <= n; i++) {
    		Update(1, i, pre[i], 1, n);
    		if(pre[i]) Update(1, pre[i], inf, 1, n);
    		for(int j = 0; j < q[i].size(); j++) {
    			int l = q[i][j].fi, id = q[i][j].se;
    		//cout << "searching query " << l << " " << i <<"
    ";
    			pair <int, int> node = Query(1, l, i, 1, n);
    			if(node.fi < l) {
    				ans[id] = node.se;
    			}
    			else ans[id] = 0;
    		}
    	}
    	for(int i = 1; i <= m; i++) printf("%d
    ", ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    ZEat
    BingWallpaper
    ZBreak
    C语言块内变量回收问题
    Android 隐藏RadoiButton左边按钮
    php文件管理与基础功能的实现
    Ajax写分页查询(实现不刷新页面)
    jquery写日期选择器
    ajax三级联动下拉菜单
    ajax bookstrap美化网页,并实现页面的加载,删除与查看详情
  • 原文地址:https://www.cnblogs.com/LiM-817/p/10887234.html
Copyright © 2011-2022 走看看