J.Different Integers

题意就是给你l,r,问你在区间两侧的[1,l]和[r,n]中,不同数的个数。

两种思路:

1.将数组长度扩大两倍,for(int i=n+1;i<=2*n;i++) a[i]=a[i-n];就可以将两个分开的区间合并成一个区间[r,l+n],然后就可以通过主席树求解,套模板就可以了。

但是用主席树有风险,容易写超时,超内存,只能通过50%,初始化数组memset少写一个就过了,而且while(scanf("%d%d",&n,&m)==2)要写成这样,我赛后试了一下while(~scanf("%d%d",&n,&m)),过不了,只能过50%,所以主席树正好卡过去。

代码:

 1 //J-主席树刚好卡过
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<vector>
 6 #include<algorithm>
 7 #include<cmath>
 8 #include<cstdlib>
 9 #include<queue>
10 using namespace std;
11 const int maxn=2*1e5+100;
12
13 struct Node
14 {
15     int l,r,sum;
16
17 }p[maxn*200];
18 int la[maxn],a[maxn],root[maxn];
19 int n,q,cnt;
20
21 int build(int l,int r)
22 {
23     int nc=++cnt;
24     p[nc].sum=0;
25     p[nc].l=p[nc].r=0;
26     if(l==r){
27         return nc;
28     }
29
30     int m=l+r>>1;
31     p[nc].l=build(l,m);
32     p[nc].r=build(m+1,r);
33     return nc;
34 }
35 int update(int pos,int c,int v,int l,int r)
36 {
37     int nc=++cnt;
38     p[nc]=p[c];
39     p[nc].sum+=v;
40     if(l==r){
41         return nc;
42     }
43
44     int m=l+r>>1;
45     if(m>=pos)
46         p[nc].l=update(pos,p[c].l,v,l,m);
47     else
48         p[nc].r=update(pos,p[c].r,v,m+1,r);
49     return nc;
50 }
51 int query(int pos,int c,int l,int r)
52 {
53     if(l==r) return p[c].sum;
54     int m=l+r>>1;
55     if(m>=pos)
56         return p[p[c].r].sum + query(pos,p[c].l,l,m);
57     else
58         return query(pos,p[c].r,m+1,r);
59 }
60 int main()
61 {
62     while(scanf("%d%d",&n,&q)==2){
63         memset(la,-1,sizeof(la));
64         cnt=0;
65         for (int i=1;i<=n;i++){
66             scanf("%d",a+i);
67         }
68         for(int i=n+1;i<=2*n;i++)
69             a[i]=a[i-n];
70         n=n*2;
71         root[0]=build(1,n);
72         for (int i=1;i<=n;i++){
73             int v=a[i];
74             if(la[v]==-1)
75                 root[i]=update(i,root[i-1],1,1,n);
76             else{
77                 int t=update(la[v],root[i-1],-1,1,n);
78                 root[i]=update(i,t,1,1,n);
79             }
80             la[v]=i;
81         }
82         while(q--){
83             int x,y;
84             scanf("%d%d",&x,&y);
85             printf("%d\n",query(y,root[n/2+x],1,n));
86         }
87     }
88 }

2.叉姐官方题解思路是树状数组,离线按照 r 从小到大处理询问,考虑没出现的数字个数,假设 r = last[x],那么当 l < first[x] 时,x 没出现,用树状数组维护即可。

唉,真的是长的帅又厉害代码写的还优美,代码写的真的是好看,羡慕(✧◡✧)

代码:(叉姐代码)

 1 #include <bits/stdc++.h>
 2
 3 struct Query
 4 {
 5     int l, r, id;
 6 };
 7
 8 bool operator < (const Query& u, const Query& v)
 9 {
10     return u.r < v.r;
11 }
12
13 int main()
14 {
15     int n, q;
16     while (scanf("%d%d", &n, &q) == 2) {
17         std::vector<int> a(n), first(n, -1), last(n);
18         int total = 0;
19         for (int i = 0; i < n; ++ i) {
20             scanf("%d", &a[i]);
21             a[i] --, last[a[i]] = i;
22             if (first[a[i]] == -1) {
23                 total ++, first[a[i]] = i;
24             }
25         }
26         std::vector<Query> queries;
27         for (int i = 0, l, r; i < q; ++ i) {
28             scanf("%d%d", &l, &r);
29             queries.push_back(Query {l - 1, r - 1, i});
30         }
31         std::sort(queries.begin(), queries.end());
32         std::vector<int> count(n), result(q);
33         for (int i = 0, k = 0; i < n; ++ i) {
34             while (k < q && queries[k].r == i) {
35                 int& ref = result[queries[k].id] = total;
36                 for (int j = queries[k].l; j < n; j += ~j & j + 1) {
37                     ref -= count[j];
38                 }
39                 k ++;
40             }
41             if (last[a[i]] == i) {
42                 for (int j = first[a[i]] - 1; ~j; j -= ~j & j + 1) {
43                     count[j] ++;
44                 }
45             }
46         }
47         for (int i = 0; i < q; ++ i) {
48             printf("%d\n", result[i]);
49         }
50     }
51 }

自己改了一下叉姐代码加了一点注释的代码:

 1 //J-离线树状数组处理
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<map>
 9 #include<vector>
10 using namespace std;
11 const int maxn=1e5+10;
12 const int inf=0x3f3f3f3f;
13 const double eps=1e-5;
14 struct node
15 {
16     int l,r,id;
17     bool operator< (const node &a) const{   //结构体内嵌比较函数
18         return r<a.r;
19     }
20 };
21 int main()
22 {
23     int n,q;
24     while(~scanf("%d%d",&n,&q)){
25         vector<int>a(n),first(n, -1),last(n);
26         int total=0;
27         for (int i=0;i<n;i++){
28             scanf("%d",&a[i]);
29             a[i]--,last[a[i]]=i;//记录元素最后出现的位置
30             if(first[a[i]]==-1){//如果元素之前未出现,则记录第一次出现的位置
31                 total++;
32                 first[a[i]]=i;
33             }
34         }
35         vector<node> queries;
36         for (int i=0;i<q;i++) {
37             int l,r;
38             scanf("%d%d",&l,&r);
39             queries.push_back(node {l-1,r-1,i});//将区间和id存到容器内
40         }
41         sort(queries.begin(),queries.end());//区间右边界升序排序(结构体内内嵌了比较函数)
42         vector<int>count(n),result(q);
43         for (int i=0,k=0;i<n;i++){//树状数组维护
44             while(k<q&&queries[k].r==i){
45                 int &ref=result[queries[k].id]=total;
46                 for(int j=queries[k].l;j<n;j+=~j&j+1){//~j&j+1 +的优先级比&高
47                     ref-=count[j];
48                 }
49                 k++;
50             }
51             if(last[a[i]]==i){
52                 for(int j=first[a[i]]-1;~j;j-=~j&j+1){
53                     count[j]++;//统计没有出现过的元素个数
54                 }
55             }
56         }
57         for (int i=0;i<q;i++) {
58             printf("%d\n",result[i]);
59         }
60     }
61 }

讲道理,我是真的菜,难受。

转载于:https://www.cnblogs.com/ZERO-/p/9346176.html

牛客网 暑期ACM多校训练营(第一场)J.Different Integers-区间两侧不同数字的个数-离线树状数组 or 可持久化线段树(主席树)...相关推荐

  1. 牛客网暑期ACM多校训练营(第二场):J. farm(暴力)

    链接:https://www.nowcoder.com/acm/contest/140/J 来源:牛客网 题目描述 White Rabbit has a rectangular farmland of ...

  2. 2018牛客网暑期ACM多校训练营第二场 D - money(贪心)

    题目链接 https://www.nowcoder.com/acm/contest/140#question [题目描述] White Cloud is exercising in the playg ...

  3. 牛客网暑期ACM多校训练营(第十场)F.Rikka with Line Graph

    牛客网暑期ACM多校训练营(第十场)F.Rikka with Line Graph 做法:\(G'\) 中的对应原图两条边(a,b) (c,d)的最短路为: \[ w[a][b] + w[c][d] ...

  4. 牛客网暑期ACM多校训练营(第九场)

    牛客网暑期ACM多校训练营(第九场) A. Circulant Matrix 做法:看到下标 \(xor\) 这种情况就想 \(FWT\),可是半天没思路,于是放弃了..其实这个 \(n\) 疯狂暗示 ...

  5. 牛客网暑期ACM多校训练营(第五场)

    牛客网暑期ACM多校训练营(第五场) A. gpa 二分答案,然后就转化为是否满足 \(\frac {\sum s[i]c[i]}{\sum s[i]} ≥ D\), \(\sum s[i]c[i] ...

  6. 牛客网暑期ACM多校训练营(第三场)

    牛客网暑期ACM多校训练营(第三场) A. PACM Team 01背包,输出方案,用bool存每种状态下用的哪一个物品,卡内存.官方题解上,说用char或者short就行了.还有一种做法是把用的物品 ...

  7. 牛客网暑期ACM多校训练营(第一场)

    牛客网暑期ACM多校训练营(第一场) A. Monotonic Matrix 考虑0和1的分界线,1和2的分界线,发现问题可以转化为两条不互相穿过的路径的方案数(可重叠),题解的做法就是把一条路径斜着 ...

  8. 牛客网暑期ACM多校训练营(第十场)D Rikka with Prefix Sum

    链接:https://www.nowcoder.com/acm/contest/148/D 来源:牛客网 题目描述 Prefix Sum is a useful trick in data struc ...

  9. 牛客网暑期ACM多校训练营(第三场)A.PACM Team(多重01背包)

    链接:https://www.nowcoder.com/acm/contest/141/A 来源:牛客网 题目描述 Eddy was a contestant participating in ACM ...

  10. 2018牛客网暑期ACM多校训练营(第十场)A Rikka with Lowbit (树状数组)

    链接:https://ac.nowcoder.com/acm/contest/148/A 来源:牛客网 Rikka with Lowbit 时间限制:C/C++ 5秒,其他语言10秒 空间限制:C/C ...

最新文章

  1. 2021年大数据Spark(四十六):Structured Streaming Operations 操作
  2. Spring Boot Admin:微服务应用监控
  3. BOOST_VMD_ASSERT_IS_EMPTY宏相关的测试程序
  4. python文件写入字典格式输出_Python把对应格式的csv文件转换成字典类型存储脚本的方法...
  5. Day11多态部分-6 【1.4 多态的应用以及注意事项】
  6. 推荐一个好用的Chrome扩展应用,管理新建标签页面的
  7. Oracle Golden Gate 系列十六 -- 配置 GG 安全 说明 与 示例
  8. Jenkins插件开发(四)-- 插件发布
  9. PowerDesigner里面将表中name列值拷贝到comment列
  10. 正则表达式 RegExp【详解】
  11. wap尝试调取app(网易新闻为例)
  12. 微信小程序自定义侧滑删除组件
  13. 震惊:爱测未来技术嘉年华竟然这些免费送
  14. _003_WindowsOperation_为什么升级win10后,很多软件打开就显示文件系统错误(-1073741819)
  15. 实现点击按钮关闭微信小程序功能(附源码)
  16. 小时代3刺金时代好看吗?
  17. matlab光线追击,MATLAB在追迹光线计算中的应用
  18. 硬盘的读写速度如何计算
  19. 百度地图-创建标注 画线
  20. EOS智能合约开发系列(16): deferred action与inline action

热门文章

  1. Vue.js学习系列(三十四)-- Vue.js样式绑定(五)
  2. 优化Nginx服务的安全配置
  3. dos定义变量算术运算逻辑运算表达式分隔符
  4. 常见的一些功能测试用例
  5. 一次 sql 优化经历,太有趣了!
  6. 技术人, 请不要封闭自己
  7. Spring 框架用到的 9 个设计模式汇总!
  8. Consul入门05 - 健康检测
  9. 从 npm 迁移至yarn
  10. C++中const用于函数重载