• 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
    ",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

  • 相关阅读:
    在Ubuntu 20.04.2 LTS上,启动samba服务
    怎么将ppt中插入的文件单独保存出来
    两款造包工具,科来和xcap
    intel 网卡 && realtek网卡 抓vlan 设定
    Spring注解和一些类
    ReentrantLock源码阅读
    UG12.0安装
    SQL SERVER 分页代码
    SQL SERVER 处理小数位数函数FU_DecimalDigits
    SQL SERVER 表和列添加备注
  • 原文地址:https://www.cnblogs.com/whdsunny/p/9350085.html
Copyright © 2020-2023  润新知