2018牛客暑期ACM多校训练营第一场(有坑未填)

(重新组队后的第一场组队赛 也是和自己队友的一次磨合吧

这场比赛真的算是一个下马威吧……队友上手一看 啊这不是莫队嘛 然后开敲 敲完提交发现t了 在改完了若干个坑点后还是依然t(真是一个悲伤的故事)然后换我上去查 在经历了一番玄幻操作之后 不知为啥就过了……

J Different Integers

 

题目大意就是一个数组, 长度n<=1e5  q次询问(l, r)  输出区间[1, l]  [r, n]中不同数字的个数  q<=1e5 

一开始上了莫队的板子 但是t掉了 后来发现题目中有个隐藏的坑点 就是存在l>r的情况 

找出坑点后 发现还是t 就想到估计要有优化 在分块的时候不用从头到尾进行分块 这也是一个t的点

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cmath>
 6 #include <algorithm>
 7 #include <string>
 8 #include <vector>
 9 #include <stack>
10 #include <queue>
11 #include <set>
12 #include <cctype>
13 #include <ctime>
14 #include <map>
15 using namespace std;
16 const int maxn=1e5+5;
17 int a[maxn];
18 int sum[maxn];
19 int num[maxn];
20 int n,q,now;
21 struct Node{
22     int l,r,id,d;
23 }node[maxn];
24 bool cmp1(Node one,Node two){
25     if(one.d!=two.d){
26         return one.d<two.d;
27     }else{
28         return one.r<two.r;
29     }
30 }
31 int main(){
32     while(~scanf("%d%d",&n,&q)){
33         int all=0;
34         for(int i=1;i<=n;i++) {
35             scanf("%d",&a[i]);num[a[i]]++;
36             if(num[a[i]]==1){
37                 all++;
38             }
39         }
40         int tmp=all;
41         int block=sqrt(n)+1;
42         for(int i=1;i<=q;i++){
43             scanf("%d%d",&node[i].l,&node[i].r);
44             node[i].l++;
45             node[i].r--;
46             node[i].d=node[i].l/block+1;
47             node[i].id=i;
48         }
49         sort(node+1,node+1+q,cmp1);
50         int l=1,r=0;
51         for(int i=1;i<=q;i++){
52             if(node[i].l>node[i].r) {sum[node[i].id]=tmp;continue;}
53             while(l<node[i].l){
54                 num[a[l]]++;
55                 if(num[a[l]]==1) all++;l++;
56             }
57             while(l>node[i].l){
58                 l--;num[a[l]]--;
59                 if(num[a[l]]==0) all--;
60             }
61             while(r<node[i].r){
62                 r++;
63                 num[a[r]]--;
64                 if(num[a[r]]==0) all--;
65             }
66             while(r>node[i].r){
67                 num[a[r]]++;
68                 if(num[a[r]]==1) all++;r--;
69             }
70             sum[node[i].id]=all;
71         }
72         for(int i=1;i<=q;i++){
73             printf("%d\n",sum[i]);
74         } 
75         for(int i=1;i<=n;i++){
76             num[a[i]]=0;
77         }
78     }
79     return 0;
80 }
View Code

后来看叉姐直播讲解的时候 发现还可以用树状数组 线段树去做 好像卡掉了主席树 因为必须要离线状态 下次研究一下树状数组的做法 同时蔡队还在弹幕中提出了一个做法 感觉很巧妙 这里也分享一下 就是把原数组扩展成两倍的长度 首位拼接 所以1-l r-n就变成了r-l+n 就直接是区间问题了(就可以愉快的套板子了)(留坑 研究完就上传代码)

 

弱鸡队艰难签到成功后 在a题和d题卡了数不清的时间 等补题完后再来填坑orz

转载于:https://www.cnblogs.com/whdsunny/p/9350085.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值