[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 } 
View Code

然而提交到洛谷上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;
} 
View Code

%%%

posted @ 2021-08-23 14:23  starlightlmy  阅读(68)  评论(0)    收藏  举报