2020ICPC·小米 网络选拔赛第一场 E-Phone Network (线段树)

题目链接:传送门

题目思路:

设 R(l,i) 表示以端点 l 为起点 包括数字 [ 1 , i ] 的最小右端点;

显然,对于 R(l,i) -> R(l,i+1) 是单调不减的(加入一个元素),R(l,i) -> R(l+1,i) 也是单调不减的(双指针思想);

那么对于这两个单调性,可以用线段树的区间赋值维护MAX来求R(l,i);

代码:

  1 #include<bits/stdc++.h>
  2 /*
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<cstring>
  6 #include<vector>
  7 #include<cctype>
  8 #include<queue>
  9 #include<algorithm>
 10 #include<map>
 11 #include<set>
 12 */
 13 //#pragma GCC optimize(2)
 14 using namespace std;
 15 typedef long long LL;
 16 typedef unsigned long long uLL;
 17 typedef pair<int,int> pii;
 18 typedef pair<LL,LL> pLL;
 19 typedef pair<double,double> pdd;
 20 const int N=2e5+5;
 21 const int M=8e5+5;
 22 const int inf=0x3f3f3f3f;
 23 const LL mod=1e8+7;
 24 const double eps=1e-8;
 25 const long double pi=acos(-1.0L);
 26 #define ls (i<<1)
 27 #define rs (i<<1|1)
 28 #define fi first
 29 #define se second
 30 #define pb push_back
 31 #define eb emplace_back
 32 #define mk make_pair
 33 #define mem(a,b) memset(a,b,sizeof(a))
 34 LL read()
 35 {
 36     LL x=0,t=1;
 37     char ch;
 38     while(!isdigit(ch=getchar())) if(ch=='-') t=-1;
 39     while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
 40     return x*t;
 41 
 42 }
 43 vector<int> e[N];
 44 int a[N],lz[N<<2],c[N<<2],mi[N<<2];
 45 inline void pushup(int i)
 46 {
 47     c[i]=min(c[ls],c[rs]);
 48     mi[i]=min(mi[ls],mi[rs]);
 49 }
 50 void pushdown(int i,int l,int r)
 51 {
 52     int &x=lz[i];
 53     lz[ls]=lz[rs]=x;
 54     mi[ls]=mi[rs]=x;
 55     int mid=r+l>>1;
 56     c[ls]=x-mid+1;
 57     c[rs]=x-r+1;
 58     x=0;
 59 }
 60 
 61 void update(int i,int l,int r,int ll,int rr,int x)
 62 {
 63     if(ll<=l&&r<=rr)
 64     {
 65         lz[i]=mi[i]=x;
 66         c[i]=x-r+1;
 67         return ;
 68     }
 69     if(lz[i]) pushdown(i,l,r);
 70     int mid=l+r>>1;
 71     if(mid>=ll) update(ls,l,mid,ll,rr,x);
 72     if(mid<rr) update(rs,mid+1,r,ll,rr,x);
 73     pushup(i);
 74 }
 75 int ask(int i,int l,int r,int ll,int rr)
 76 {
 77     if(mi[i]>=rr) return 0;
 78     if(l==r) return l;
 79     if(lz[i]) pushdown(i,l,r);
 80     int mid=l+r>>1;
 81     int pos=0;
 82     if(mid<rr) pos=ask(rs,mid+1,r,ll,rr);
 83     if(mid>=ll&&!pos) pos=ask(ls,l,mid,ll,rr);
 84     return pos;
 85 }
 86 int main()
 87 {
 88     int n=read(),m=read();
 89    // build(1,1,n);
 90     for(int i=1;i<=n;i++) a[i]=read();
 91     for(int i=1;i<=m;i++) e[i].eb(0);
 92     for(int i=1;i<=n;i++) e[a[i]].eb(i);
 93     for(int i=1;i<=m;i++)
 94     {
 95         for(int j=1;j<e[i].size();j++)
 96         {
 97             int pos=ask(1,1,n,e[i][j-1]+1,e[i][j]);        //printf("i=%d ,j=%d , pos=%d
 ",i,j,pos);
 98 
 99             if(pos>0) update(1,1,n,e[i][j-1]+1,pos,e[i][j]);
100         }
101         if(e[i].back()<n) update(1,1,n,e[i].back()+1,n,inf);
102         printf("%d ",c[1]);
103     }
104     printf("
");
105     return 0;
106 }
View Code
原文地址:https://www.cnblogs.com/DeepJay/p/13986595.html