【BZOJ1878】【SDOI2009】HH的项链
离线处理+树状数组即可。
将询问按照左端点从小到大排序,之后从左到右扫一遍,表示贝壳是否是还没扫过的贝壳中这种颜色的贝壳的第一次出现.
预处理表示这种颜色的贝壳下一次出现的地方.一开始先把每个颜色第一次出现的贝壳的加上.对于每个扫过的贝壳,给加上.
用树状数组维护,询问的答案就是.
于是这题就做完啦.
时间复杂度.
#include <cctype>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXSIZE=30000020;
int bufpos;
char buf[MAXSIZE];
void init(){
#ifdef LOCAL
freopen("1878.txt","r",stdin);
#endif // LOCAL
buf[fread(buf,1,MAXSIZE,stdin)]='\0';
bufpos=0;
}
int readint(){
bool isneg;
int val=0;
for(;!isdigit(buf[bufpos]) && buf[bufpos]!='-';bufpos++);
bufpos+=(isneg=(buf[bufpos]=='-'))?1:0;
for(;isdigit(buf[bufpos]);bufpos++)
val=val*10+buf[bufpos]-'0';
return isneg?-val:val;
}
struct bit{
int t[50001];
int n;
void init(int n){
this->n=n;
memset(t,0,sizeof(t));
}
inline int lowbit(int x){
return (x&(-x));
}
int sum(int x){
int ret=0;
for(int i=x;i>0;i-=lowbit(i))
ret+=t[i];
return ret;
}
void add(int p,int v){
for(int i=p;i<=n;i+=lowbit(i))
t[i]+=v;
//for(int i=1;i<=n;i++)
//printf("%d ",t[i]);
}
}t;
int nxt[50001];
int now[1000001];
bool app[1000001];
int a[50001];
struct query{
int l,r,p;
bool operator <(const query& rhs)const{
return l<rhs.l;
}
};
query q[200001];
int ans[200001];
int main(){
init();
int n=readint();
t.init(n);
for(int i=1;i<=n;i++)
a[i]=readint();
int m=readint();
for(int i=1;i<=m;i++){
q[i].l=readint(),q[i].r=readint(),q[i].p=i;
}
sort(q+1,q+m+1);
memset(now,-1,sizeof(now));
for(int i=n;i>=1;i--){
nxt[i]=now[a[i]];
now[a[i]]=i;
}
for(int i=1;i<=n;i++){
if (!app[a[i]])
t.add(i,1),app[a[i]]=true;
}
q[0].l=1;
for(int i=1;i<=m;i++){
for(int j=q[i-1].l;j<q[i].l;j++)
if (nxt[j]!=-1)
t.add(nxt[j],1);
ans[q[i].p]=t.sum(q[i].r)-t.sum(q[i].l-1);
}
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
本文链接:https://www.q234rty.top/2016/06/18/bzoj1878/