洛谷 P1972 [SDOI2009]HH的项链
来源:互联网 发布:js availheight 编辑:程序博客网 时间:2024/06/14 13:23
法一:树状数组,离线
翻译:
给出一个数列a[n]还有许多请求,请求由l,r两个数组成,要求对于每个请求输出数列中从a[l]到a[r]中不重复的数的个数。
方法:
首先读入数列a[n],并预处理next1,boo两个辅助数组,方法见程序。
然后读入请求,把请求按l从小到大排序,并记录原来序号方便输出。
(本题中,为了方便说明,用tree[i]表示可通过sum(i,i)求出的树状数组中第i项的值(不是指c[i]))
开始前,对于每个第一次出现的数所在的位置t,使tree[t]++,即add(t,1)。这样,如果请求的l是1,就可以通过sum(l,r)得出答案。但是,如果请求的左端点大于1,就不能这样做了。
例如,当请求的l是5时,在a[5]到a[r]中,可能有一些数与a[1]到a[4]中的数相同,且它们如果从第1个数开始数不是第一次出现的,但如果从第5个数开始数就是第一次出现的。因此,在处理这个请求的时候,就需要先找到tree[1]到tree[4]中所有不为0的数tree[x],先将tree[x]减1(由于tree[1]到tree[4]实际上不会影响sum(5,r)的结果,因此不减也没关系),再找到与a[x]相同的下一个数t,也就是next1[x]的值,然后将tree[t]加1(如果next1[x]为0,指的就是没有下一个与a[x]相同的数,则不需进行此操作)。例如有一个数tree[1]为1,那么就先将tree[1]减1(不减也行),然后如果next1[1]不为0,则将tree[next1[1]]加1。
由此可得出,需要按排序后的顺序来处理请求,对于请求q[i],如果q[i-1].l<q[i].l,则需要将tree[q[i-1].l]到tree[q[i].l-1]都按以上的方法进行处理,之后才能用sum(q[i].l,q[i].r)得出结果。
最后不要忘了按原来的询问顺序输出结果。
#include<cstdio>#include<algorithm>using namespace std;typedef long long LL;LL a[51000];LL c[400100];LL next1[51000];//next1[i]记录第i个数字下一次出现的位置LL ans[201000];LL boo[1001000];//boo[i]记录数字i第一次出现位置LL n,m,x,k=1,lastk;struct query1{ LL l,r; LL num,ans; friend bool operator<(query1 a,query1 b) { return (a.l==b.l&&a.r<b.r)||a.l<b.l;//如果a.r<=b.r则RE,不明原因?? }}q[200100];LL lowbit(LL x){ return x&-x;}void add(LL num,LL x){ while(num<=n) { c[num]+=x; num+=lowbit(num); }}LL sum1(LL x){ LL ans=0; while(x>0) { ans+=c[x]; x-=lowbit(x); } return ans;//曾经忘记返回值 }LL sum(LL l,LL r){ return sum1(r)-sum1(l-1);}int main(){ LL i,j,p; scanf("%lld",&n); for(i=1;i<=n;i++) { scanf("%lld",&a[i]); a[i]++; } for(i=n;i>=1;i--)//优化为倒序 next1[i]=boo[a[i]],boo[a[i]]=i;//方便找到某数字第一次出现位置与下一次出现的位置(链式的),弄几组数据试试就能明白 for(i=1;i<=n;i++) if(boo[a[i]]==i) add(i,1); scanf("%lld",&m); for(i=1;i<=m;i++) { scanf("%lld%lld",&q[i].l,&q[i].r); q[i].num=i; } sort(q+1,q+m+1); for(i=1;i<=m;i++) { //if(q[i].l>q[i-1].l)//后面去掉的,因为没用 //{ lastk=k; k=q[i].l; for(j=lastk;j<k;j++) { //add(j,-1);//后面去掉的,因为不需要更新,后面答案与此无关 if(next1[j]!=0) add(next1[j],1); //boo[j]=next1[j];//后面去掉的,因为boo数组不再有用 } //} ans[q[i].num]=sum(q[i].l,q[i].r); //q[i].ans=sum(q[i].l,q[i].r); } for(i=1;i<=m;i++) printf("%lld\n",ans[i]); //sort(q+1,q+m+1,cmp2); //for(i=1;i<=m;i++) //printf("%lld\n",q[i].ans);//另一种输出方式 return 0;}
法二:莫队算法
- 洛谷 P1972 [SDOI2009]HH的项链
- 洛谷 P1972 [SDOI2009]HH的项链
- 【bzoj1878】【洛谷P1972】【SDOI2009】HH的项链
- 洛谷 P1972 [SDOI2009]HH的项链
- [SDOI2009]HH的项链 洛谷p1972
- 洛谷P1972:[SDOI2009]HH的项链(莫队/线段树)
- 洛谷P1972 [SDOI2009]HH的项链(BZOJ1878)
- [SDOI2009] 洛谷P1972 HH的项链-------离线方法 && 在线主席树
- 洛谷 P1972 [SDOI2009]HH的项链 (可持久化线段树)
- (洛谷)[SDOI2009]HH的项链
- [SDOI2009]HH的项链
- 【SDOI2009】HH的项链
- [SDOI2009]HH的项链
- bzoj1878/洛谷1972 [SDOI2009]HH的项链
- [BZOJ1878][SDOI2009]HH的项链
- [BZOJ1878] [SDOI2009]HH的项链
- 【SDOI2009】【BZOJ1878】HH的项链
- 【bzoj1878】[SDOI2009]HH的项链
- Spring WebSocket初探1 (Spring WebSocket入门教程)
- 端口的作用
- Android Toolbar的使用
- 二叉堆
- STL中提供-二分查找算法(binary_search lower_bound upper_bound equal_range)
- 洛谷 P1972 [SDOI2009]HH的项链
- Hibernate
- Java中堆内存和栈内存详解
- Thinkphp 引入dll类步奏
- 存储能力惊人 哈佛科学家将一部电影上传到了DNA中
- pdb for debug
- FlexBox 布局属性概念梳理
- 多重背包优化
- centos6安装xgboost0.6