#树状数组#洛谷 4113 [HEOI2012]采花

题目


分析

HH的项链类似
离线处理询问,按右端点排序,维护最近的颜色和第二近的颜色,修改以第二近的颜色为准
换句话说,若最近颜色的位置为(pos2),第二近颜色的位置为(pos1)
加入一个颜色(j)时,将(pos1)更新为(pos2),将(pos2)更新为(j),注意树状数组删除(pos1),添加(pos2)


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int N=2000011; struct rec{int l,r,rk;}b[N];
int n,m,ans[N],a[N],c[N],pos1[N],pos2[N];
inline signed iut(){
    rr int ans=0; rr char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    return ans;
}
inline void print(int ans){
    if (ans>9) print(ans/10);
    putchar(ans%10+48);
}
bool cmp(rec t1,rec t2){return t1.r<t2.r;}
inline void add(int x,int y){for (;x<=n;x+=-x&x) c[x]+=y;}
inline signed query(int l,int r){
	rr int ans=0; --l;
	for (;r>l;r-=-r&r) ans+=c[r];
	for (;l>r;l-=-l&l) ans-=c[l];
	return ans;
}
signed main(){
    n=iut(),iut(),m=iut();
	for (rr int i=1;i<=n;++i) a[i]=iut();
    for (rr int i=1;i<=m;++i) b[i]=(rec){iut(),iut(),i};
    sort(b+1,b+1+m,cmp); rr int now=1;
    for (rr int i=1;i<=m;++i){
        for (rr int j=now;j<=b[i].r;++j)
		if (!pos2[a[j]]) pos2[a[j]]=j;
		else if (!pos1[a[j]]) add(pos2[a[j]],1),pos1[a[j]]=j;
		else add(pos2[a[j]],-1),add(pos1[a[j]],1),
			pos2[a[j]]=pos1[a[j]],pos1[a[j]]=j;
        now=b[i].r+1,ans[b[i].rk]=query(b[i].l,b[i].r);
    }
    for (rr int i=1;i<=m;++i) print(ans[i]),putchar(10);
    return 0;
}
原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13527145.html