1. 程式人生 > 實用技巧 >2020ICPC·小米 網路選拔賽第一場 E-Phone Network (線段樹)

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\n ",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("\n"); 105 return 0; 106 }
View Code