【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 LOCALfreopen("1878.txt","r",stdin);#endif // LOCALbuf[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/
