zoukankan      html  css  js  c++  java
  • luogu4113 [HEOI2012]采花

    https://www.luogu.org/problemnew/show/P4113

    简化版题意:求出区间中有几个数出现了两次以上

    题目要求出现两次以上,而且出现 10 次对答案只产生 1 的贡献,可以考虑对数字做一些变化

    原数组:1 2 3 2 3 3 1 权值数组:0 0 0 1 1 0 1

    对于在区间中出现第二次的数的权值为 1,其余为 0,这样只需要树状数组维护一下区间和就行了

    将所有询问按照 l 排序,将 l 相同的做掉,不相同的可以在树状数组上修改,对于一个 l 如果不可能出现在询问中后,可以将其删除,令 pre[x] 表示数组下标为 x 的数后一个和它相同的数的数组下标(可能有点绕),我们将 pre[x] 位置上的数 -1, 将 pre[pre[x]] 位置上的数 +1即可

    复杂度 n log n

    #include <bits/stdc++.h>
    #define For(i, a, b) for(int i = a; i <= b; i++)
    using namespace std;
    
    typedef unsigned long long ull;
    typedef long long ll;
    
    template <typename _T>
    inline void read(_T &f) {
        f = 0; _T fu = 1; char c = getchar();
        while(c < '0' || c > '9') {if(c == '-') fu = -1; c = getchar();}
        while(c >= '0' && c <= '9') {f = (f << 3) + (f << 1) + (c & 15); c = getchar();}
        f *= fu;
    }
    
    const int N = 2000000 + 10;
    
    inline int lowbit(int x) {return x & -x;}
    
    int f[N], pre[N], now[N], a[N], Ans[N], cnt[N]; // now 维护数组下标 
    int n, col, m;
    
    void add(int x, int y) {
    	for(int i = x; i <= n; i += lowbit(i)) f[i] += y;
    }
    
    int query(int x) {
    	int ans = 0;
    	for(int i = x; i; i -= lowbit(i)) ans += f[i];
    	return ans;
    }
    
    void del(int x) {
    	if(pre[x]) add(pre[x], -1);
    	if(pre[x] && pre[pre[x]]) add(pre[pre[x]], 1);
    }
    
    struct ele {
    	int l, r, id;
    	bool operator < (const ele A) const {return l < A.l;}
    }Q[N];
    
    int main() {
    	read(n); read(col); read(m);
    	for(int i = 1; i <= n; i++) {
    		read(a[i]);
    		if(now[a[i]]) pre[now[a[i]]] = i;
    		if(cnt[a[i]] == 1) add(i, 1);
    		now[a[i]] = i; cnt[a[i]]++;
    	}
    	for(int i = 1; i <= m; i++) {
    		read(Q[i].l); read(Q[i].r);
    		Q[i].id = i;
    	}
    	sort(Q + 1, Q + m + 1);
    	int t = 1;
    	for(int i = 1; i <= m; i++) {
    		while(Q[i].l > t) del(t), t++;
    		Ans[Q[i].id] = query(Q[i].r) - query(Q[i].l - 1);
    	}
    	for(int i = 1; i <= m; i++) printf("%d
    ", Ans[i]);
    	return 0;
    } 
    
  • 相关阅读:
    我不想写题解的题们
    [清华集训2012]模积和
    2013杭电warm up1 Rotation Lock Puzzle
    2013杭电warm_up1 1010 Difference Between Primes
    2013 Multi-University Training Contest 3 (g) The Unsolvable Problem
    2013杭电warm up1 1002 Pet 求树结点的高度
    hdu 3789 奥运排序问题 模拟
    13杭电warmup1 1001 Children's Day
    2013杭州网络预选赛 1004 Save Labman No.004 求异面直线之间距离
    2013成都网络预选赛 1010 A Bit Fun
  • 原文地址:https://www.cnblogs.com/LJC00118/p/9611006.html
Copyright © 2011-2022 走看看