(重新组队后的第一场组队赛 也是和自己队友的一次磨合吧
这场比赛真的算是一个下马威吧……队友上手一看 啊这不是莫队嘛 然后开敲 敲完提交发现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 ",sum[i]); 74 } 75 for(int i=1;i<=n;i++){ 76 num[a[i]]=0; 77 } 78 } 79 return 0; 80 }
后来看叉姐直播讲解的时候 发现还可以用树状数组 线段树去做 好像卡掉了主席树 因为必须要离线状态 下次研究一下树状数组的做法 同时蔡队还在弹幕中提出了一个做法 感觉很巧妙 这里也分享一下 就是把原数组扩展成两倍的长度 首位拼接 所以1-l r-n就变成了r-l+n 就直接是区间问题了(就可以愉快的套板子了)(留坑 研究完就上传代码)
弱鸡队艰难签到成功后 在a题和d题卡了数不清的时间 等补题完后再来填坑orz