[HEOI2012]采花 离线+树状数组
题目链接:C-[HEOI2012]采花_牛客竞赛数据结构专题班树状数组、线段树练习题 (nowcoder.com)
参考博客:题解 P4113 【[HEOI2012]采花】 - wangjyqh 的博客 - 洛谷博客 (luogu.com.cn)
受益良多。
原本我自己的写法是没有排序的,我定义了一个vector,将区间右端点相同的区间的下标存到一起,在一遍for循环里枚举区间结束位置。
时间复杂度大概是 O(nlogn*小常数)
1 #include<bits/stdc++.h> //树状数组 单点更新 2 #define ll long long 3 using namespace std; 4 const int N = 2000005; 5 int T,n,m,c; 6 int pre2[N],pre1[N]; 7 ll a[N]={0},x[N],ans[N]; 8 bool vis[N]; 9 struct node{ 10 int l,r; 11 }d[N]; 12 vector<int>v[N]; 13 14 inline int lowbit(int x){ 15 return x&-x; 16 } 17 18 void update(int i,int k){ 19 while(i<=n){ 20 a[i]+=k; 21 i+=lowbit(i); 22 } 23 } 24 25 ll sum(int ii){ 26 ll res=0; 27 while(ii>0){ 28 res+=a[ii]; 29 ii-=lowbit(ii); 30 } 31 return res; 32 } 33 34 int main(){ 35 memset(pre1,-1,sizeof(pre1)); 36 memset(pre2,-1,sizeof(pre2)); 37 scanf("%d%d%d",&n,&c,&m); 38 for(int i=1;i<=n;i++){ 39 scanf("%d",&x[i]); 40 } 41 for(int i=1;i<=m;i++){ 42 scanf("%d%d",&d[i].l,&d[i].r); 43 v[d[i].r].push_back(i); 44 } 45 for(int i=1;i<=n;i++){ //结束位置 46 if(pre2[x[i]]!=-1){ 47 update(pre1[x[i]],1); 48 update(pre2[x[i]],-1); 49 pre2[x[i]]=pre1[x[i]]; 50 pre1[x[i]]=i; 51 } 52 else if(pre1[x[i]]!=-1){ 53 update(pre1[x[i]],1); 54 pre2[x[i]]=pre1[x[i]]; 55 pre1[x[i]]=i; 56 } 57 else{ 58 pre1[x[i]]=i; 59 } 60 for(int j=0;j<v[i].size();j++){ 61 int id=v[i][j]; 62 ans[id]=sum(d[id].r)-sum(d[id].l-1); 63 } 64 } 65 for(int i=1;i<=m;i++) printf("%lld\n",ans[i]); 66 return 0; 67 }
然而提交到洛谷上tle了一个点,呜呜呜
这位大佬的写法是将区间离线读入,再按区间右端点递增顺序排列,时间复杂度 O(nlogn)
在我的代码基础上修改之后的code:
#include<bits/stdc++.h> #define ll long long using namespace std; const int N = 2000005; int T,n,m,c; int pre2[N],pre1[N]; ll a[N]={0},x[N],ans[N]; bool vis[N]; struct node{ int l,r; int id; bool operator < (const node &aa) const{ return r<aa.r; } }d[N]; inline int lowbit(int x){ return x&-x; } void update(int i,int k){ while(i<=n){ a[i]+=k; i+=lowbit(i); } } ll sum(int ii){ ll res=0; while(ii>0){ res+=a[ii]; ii-=lowbit(ii); } return res; } int main(){ memset(pre1,-1,sizeof(pre1)); memset(pre2,-1,sizeof(pre2)); scanf("%d%d%d",&n,&c,&m); for(int i=1;i<=n;i++){ scanf("%d",&x[i]); } for(int i=1;i<=m;i++){ scanf("%d%d",&d[i].l,&d[i].r); d[i].id=i; } sort(d+1,d+m+1); int pos=1; for(int i=1;i<=m;i++){ while(pos<=d[i].r){ if(pre2[x[pos]]!=-1){ update(pre1[x[pos]],1); update(pre2[x[pos]],-1); pre2[x[pos]]=pre1[x[pos]]; pre1[x[pos]]=pos; } else if(pre1[x[pos]]!=-1){ update(pre1[x[pos]],1); pre2[x[pos]]=pre1[x[pos]]; pre1[x[pos]]=pos; } else{ pre1[x[pos]]=pos; } ++pos; } ans[d[i].id]=sum(d[i].r)-sum(d[i].l-1); } for(int i=1;i<=m;i++) printf("%lld\n",ans[i]); return 0; }
%%%

浙公网安备 33010602011771号