题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4747
这道题是我去年刚入校队的时候参加网赛的题目。
一年过去了,我依然还是不会做。。
这是我难题计划的开始吧。。
竟然还敲挫了,自己真是弱。
题意:
给你一个数列a,定义Mex[L,R]为a[L,R]中没有出现过的最小的自然数。求1<=l<=r<=n的所有Mex[l,r]之和。
解法我也是看了解题报告才知道的。
请参看cxlove大神的博文:http://blog.csdn.net/acm_cxlove/article/details/11749383
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <set> 5 using namespace std; 6 7 typedef long long LL; 8 typedef pair<int,int> PII; 9 const int MAX_N = 2e5+100; 10 LL delta[MAX_N<<2],sum[MAX_N<<2],maxn[MAX_N<<2]; 11 PII b[MAX_N]; 12 int a[MAX_N],next[MAX_N],n; 13 set<int> Set; 14 15 void push_down(int idx,int l,int r){ 16 if( delta[idx]!=-1 ){ 17 int m = l+r>>1; 18 sum[idx<<1] = (m-l+1)*delta[idx]; 19 sum[idx<<1|1] = (r-m)*delta[idx]; 20 delta[idx<<1] = delta[idx<<1|1] = maxn[idx<<1] = maxn[idx<<1|1] = delta[idx]; 21 delta[idx] = -1; 22 } 23 } 24 25 void push_up(int idx){ 26 sum[idx] = sum[idx<<1]+sum[idx<<1|1]; 27 maxn[idx] = max(maxn[idx<<1],maxn[idx<<1|1]); 28 } 29 30 void update(int L,int R,LL x,int idx,int l,int r){ 31 if( R<l||L>r ) return; 32 if( L<=l&&R>=r ) { 33 sum[idx] = (r-l+1)*x; 34 maxn[idx] = delta[idx] = x; 35 return; 36 } 37 push_down(idx,l,r); 38 int m = l+r>>1; 39 if( L<=m ) update(L,R,x,idx<<1,l,m); 40 if( R>m ) update(L,R,x,idx<<1|1,m+1,r); 41 push_up(idx); 42 } 43 44 int query(LL x,int idx,int l,int r){ 45 if( maxn[idx]<=x ) return r+1; 46 if( l==r ) return l; 47 push_down(idx,l,r); 48 int m = l+r>>1; 49 if( maxn[idx<<1]>x ) return query(x,idx<<1,l,m); 50 else return query(x,idx<<1|1,m+1,r); 51 } 52 53 LL querySum(int L,int R,int idx,int l,int r){ 54 if( L<=l&&R>=r ) return sum[idx]; 55 push_down(idx,l,r); 56 int m = l+r >> 1 ; 57 LL res = 0; 58 if( L<=m ) res = querySum(L,R,idx<<1,l,m); 59 if( R>m ) res += querySum(L,R,idx<<1|1,m+1,r); 60 return res; 61 } 62 63 int main(){ 64 while(scanf("%d",&n)!=EOF&&n){ 65 memset(sum,0,sizeof(sum)); 66 memset(delta,-1,sizeof(delta)); 67 Set.clear(); 68 for(int i=1;i<=n;i++){ 69 scanf("%d",&a[i]); 70 b[i] = PII(a[i],i); 71 next[i] = n+1; 72 } 73 sort(b+1,b+1+n); 74 b[n+1].first = b[n].first; b[n+1].second = n+1; 75 for(int i=1;i<=n;i++){ 76 if( b[i].first==b[i+1].first ) next[b[i].second] = b[i+1].second; 77 } 78 int mmex = 0; 79 for(int i=1;i<=n;i++){ 80 Set.insert(a[i]); 81 while( Set.find(mmex)!=Set.end() ) mmex++; 82 update(i,i,mmex,1,1,n); 83 } 84 LL ans = sum[1]; 85 for (int l = 1; l <= n; l++) { 86 update(l,l,0,1,1,n); 87 int p = query(a[l],1,1,n); 88 p = max(l+1,p); 89 int q = next[l] - 1; 90 update(p,q,a[l],1,1,n); 91 ans += sum[1]; 92 } 93 printf("%I64d\n", ans); 94 } 95 return 0; 96 }
时间: 2024-10-12 23:06:47