Luogu P1972 [SDOI2009] HH's necklace (offline + tree array)

Original question link
Question meaning:
Find the number of different elements in the interval.
Idea: It
should also be possible to use the chairman tree (if I can .jpg).
For a section, the effective position of each element is the rightmost position.
For example, 1 2 3 4 1, when querying the interval [i,5], the 1 in the 1 position is useless, so for each number, only the rightmost position in a certain interval needs to be maintained.
Store all the queries, sort them by r, and use a tree array to maintain how many different numbers are in 1~i. The answer is qask (r )-qask(l-1); record each element in the current query interval At the rightmost position that appears, if the element reappears, the contribution of the last position is subtracted, and the contribution of this position is added.
Code:

#pragma GCC optimize(3)
///#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll>PLL;
typedef pair<int,int>PII;
typedef pair<double,double>PDD;
#define I_int ll
inline ll read()
{
    
    
    ll x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
    
    
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
    
    
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
char F[200];
inline void out(I_int x)
{
    
    
    if (x == 0) return (void) (putchar('0'));
    I_int tmp = x > 0 ? x : -x;
    if (x < 0) putchar('-');
    int cnt = 0;
    while (tmp > 0)
    {
    
    
        F[cnt++] = tmp % 10 + '0';
        tmp /= 10;
    }
    while (cnt > 0) putchar(F[--cnt]);
    //cout<<" ";
}
ll ksm(ll a,ll b,ll p)
{
    
    
    ll res=1;
    while(b)
    {
    
    
        if(b&1)res=res*a%p;
        a=a*a%p;
        b>>=1;
    }
    return res;
}
const int inf=0x3f3f3f3f,mod=998244353;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int maxn=2e6+100,maxm=3e5+7,N=1e6+7;
const double PI = atan(1.0)*4;
int a[maxn],n,m;
struct node{
    
    
    int l,r;
    int pos;
}q[maxn];
int vis[maxn],las;
int res[maxn];
bool cmp(node a,node b){
    
    
    return a.r<b.r;
}
int tr[maxn];
int lowbit(int x){
    
    
    return x&-x;
}
void update(int pos,int val){
    
    
    while(pos<=n) tr[pos]+=val,pos+=lowbit(pos);
}
int qask(int pos){
    
    
    int res=0;
    while(pos) res+=tr[pos],pos-=lowbit(pos);
    return res;
}
int main(){
    
    
	n=read();
	for(int i=1;i<=n;i++) a[i]=read();
	m=read();
	for(int i=1;i<=m;i++){
    
    
        q[i].l=read(),q[i].r=read();
        q[i].pos=i;
	}
	sort(q+1,q+1+m,cmp);
	int last=1;
	for(int i=1;i<=m;i++){
    
    
        for(int j=last;j<=q[i].r;j++){
    
    
            if(vis[a[j]]) update(vis[a[j]],-1);
            vis[a[j]]=j;
            update(j,1);
        }
        last=q[i].r+1;
        res[q[i].pos]=qask(q[i].r)-qask(q[i].l-1);
	}
	for(int i=1;i<=m;i++) printf("%d\n",res[i]);
	return 0;
}







reference:

Guess you like

Origin blog.csdn.net/weixin_45675097/article/details/110292870