zoukankan      html  css  js  c++  java
  • 【loj2461】【2018集训队互测Day 1】完美的队列

    #2461. 「2018 集训队互测 Day 1」完美的队列

    传送门: 

    https://loj.ac/problem/2461

    题解:

            直接做可能一次操作加入队列同时会弹出很多数字,无法维护;一个操作的有效区间是连续的,考虑找到操作x结束的时间ed[x],即执行(x,ed[x]]可以将x加入的数全部弹出,这样用一个vis记录数字次数就可以维护个数;

            一种比较暴力的做法是:枚举x,用一个线段树维护还可以放多少个元素,枚举ed[x]更新,但是这样不满足单调性无法two-pointers;

            考虑分块。ed[x]即对x的每一个块的ed取max

            考虑整块。枚举每一个整块,用一个b维护还可以放的元素初始化为ai,cov维护整块被完整覆盖了多少次,枚举x,再枚举ed[x],当mx(bi)-cov==0时表示x的当前块在这里结束,更新ed[x],此时是有单调性的可以two-pointers,复杂度$O(m sqrt{n})$;

           考虑散块。在处理完整块的时候枚举整块里的元素处理散块,如果直接像整块那样枚举m个操作,复杂度是$O(nm)$的,但如果在处理整块时用一个d数组记录下每一个和当前整块相交但不覆盖的操作,这样就是$O(m sqrt{n})$的,因为一个操作最多有$sqrt{n}$个散块,同样枚举d的元素做two-pointers,注意这是一个散块的ed不一定只出现在d里,可能出现在d[i]和d[i-1]中间某个将整块完整覆盖的操作,所以还需要记录完全覆盖整块的操作的前缀和s[],  覆盖整块的编号c[] , d[i]前面的第一个覆盖整块的操作e[i]。

             细节多;

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<queue>
     6 #include<cmath>
     7 #include<vector>
     8 #include<stack>
     9 #include<map>
    10 #define Run(i,l,r) for(int i=l;i<=r;i++)
    11 #define Don(i,l,r) for(int i=l;i>=r;i--)
    12 #define ll long long
    13 #define inf 0x3f3f3f3f
    14 using namespace std;
    15 const int N=100010;
    16 int n,m,a[N],b[N],c[N],d[N],e[N],vis[N],num,cn,dn,l[N],r[N],v[N],ed[N],s[N];
    17 inline void upd(int&x,int y){if(x<y)x=y;}
    18 struct node{int x,y;};
    19 vector<node>g[N];
    20 char gc(){
    21     static char*p1,*p2,S[1000000];
    22     if(p1==p2)p2=(p1=S)+fread(S,1,1000000,stdin);
    23     return(p1==p2)?EOF:*p1++; 
    24 }//
    25 int rd(){
    26     int x=0; char C=gc();
    27     while(C<'0'||C>'9')C=gc();
    28     while(C>='0'&&C<='9')x=(x<<1)+(x<<3)+C-'0',C=gc();
    29     return x;
    30 }//
    31 int main(){
    32     //freopen("loj2461.in","r",stdin);
    33     //freopen("loj2461.out","w",stdout);
    34     n=rd(); m=rd();
    35     Run(i,1,n)a[i]=rd();
    36     Run(i,1,m)l[i]=rd(),r[i]=rd(),v[i]=rd();
    37     int B = sqrt(n);
    38     for(int L=1;L<=n;L+=B){ 
    39         cn=dn=0;
    40         int R=min(n,L+B-1),mx=0,cov=0;
    41         Run(i,L,R)upd(mx,b[i]=a[i]);
    42         for(int i=1,j=0;i<=m;i++){
    43             if(l[i]<=L&&r[i]>=R)cov--;
    44             else if(l[i]<=R&&r[i]>=L){
    45                 Run(k,max(l[i],L),min(r[i],R))b[k]++;
    46                 mx=0;Run(k,L,R)upd(mx,b[k]);
    47             }
    48             while(j<=m&&mx-cov>0){
    49                 j++;
    50                 if(l[j]<=L&&r[j]>=R)cov++;
    51                 else if(l[j]<=R&&r[j]>=L){
    52                     Run(k,max(l[j],L),min(r[j],R))b[k]--;
    53                     mx=0;Run(k,L,R)upd(mx,b[k]);
    54                 }
    55             }
    56             s[i]=s[i-1];
    57             if(l[i]<=L&&r[i]>=R)upd(ed[i],j),s[c[++cn]=i]++;
    58             else if(l[i]<=R&&r[i]>=L)d[++dn]=i,e[dn]=cn;
    59         }//
    60         for(int i=L;i<=R;i++){
    61             mx=a[i];
    62             for(int j=1,k=0;j<=dn;j++){
    63                 mx+=s[d[j]]-s[d[j-1]];
    64                 if(l[d[j]]<=i&&r[d[j]]>=i){
    65                     mx++;    
    66                     while(k<dn&&mx>0)k++,mx-=s[d[k]]-s[d[k-1]]+(l[d[k]]<=i&&r[d[k]]>=i);
    67                     if(mx>0){
    68                         if(s[m]-s[d[k]]<mx)upd(ed[d[j]],m+1);
    69                         else upd(ed[d[j]],c[e[k]+mx]);
    70                         continue;
    71                     }
    72                     if(l[d[k]]<=i&&r[d[k]]>=i)upd(ed[d[j]],mx<0?c[e[k]+mx+1]:d[k]);
    73                     else upd(ed[d[j]],c[e[k]+mx]);
    74                 }
    75             }
    76         }//
    77     }//
    78     Run(i,1,m)g[i].push_back((node){v[i],1}),g[ed[i]].push_back((node){v[i],-1});
    79     for(int i=1;i<=m;i++){
    80         for(int j=0;j<(int)g[i].size();j++){
    81             int x=g[i][j].x,y=g[i][j].y;
    82             if((vis[x]+y==0)^(vis[x]==0))num+=y;
    83             vis[x]+=y;
    84         }
    85         printf("%d
    ",num);
    86     }
    87     return 0;
    88 }//by tkys_Austin;
    View Code
  • 相关阅读:
    荔枝派Nano (Lichee Pi)玩 Linux 傻瓜教程 (5) --- 虚拟USB网卡,SSH登录
    荔枝派Nano (Lichee Pi)玩 Linux 傻瓜教程 (4) --- 安装Python
    荔枝派Nano (Lichee Pi)玩 Linux 傻瓜教程 (3) --- TF卡扩容
    荔枝派Nano (Lichee Pi)玩 Linux 傻瓜教程 (2) --- 文件传输
    荔枝派Nano (Lichee Pi)玩 Linux 傻瓜教程 (1) --- 烧录,数据线连接登录
    RETRO MACHINE(迷你FC街机/掌机)Dump及改造
    Jetson (4)--- 人脸识别(OpenCV安装)
    Jetson (3)--- 人脸识别(Dlib安装)
    Jetson (2)--- 环境配置
    Jetson (1)--- 金属盒子按键Power,Reset线接法
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/9795846.html
Copyright © 2011-2022 走看看