2016"百度之星“-初赛(Astar Round2B)-A.区间的价值

每次取出集合中最大的数,放到它对应的位置,如1,6,2,4,4,取出6,放到1位置(从0开始)。
当你取出一个数a时,两边会有一些之前放的数, ,其中a是最小的,假设在 最大, 最大。

那么这一段连续的数可以更新长度为]的答案,而且是要包含a的一段。一段区间的有效部分是最小值到最大值的一段,我们可以先考虑有效部分,然后用它向上更新。因为a是最小值,最大值要么在b,要么在c,有效区间不会横跨b,c。并且对的答案要大于,所以对于b,只需更新,那么其实可以用去更新。同理,对c,只需用去更新


#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      
#include 
      
      
       
       
#include 
       
       
         #include 
        
          typedef long long ll; #define mst(a,k) memset(a, k, sizeof(a)) #define rep(i,s,t) for(int i = s; i < t; i++) #define lo (o << 1) #define ro (lo | 1) using namespace std; typedef pair 
         
           pii; ll Max[400005]; int n; int a[100005]; ll ans[100005]; pii b[100005]; int have[100005], head[100005], tail[100005], mx[100005]; void build(int l, int r, int o) { Max[o] = 0; if(l == r) return; int mid = l + r >> 1; build(l, mid, lo); build(mid + 1, r, ro); } void update(int l, int r, int o, int L, int R, ll v) { if(L <= l && r <= R) { Max[o] = max(Max[o], v); return; } int mid = l + r >> 1; if(L <= mid) update(l, mid, lo, L, R, v); if(mid < R) update(mid + 1, r, ro, L, R, v); } void pushdown(int l, int r, int o) { if(l == r) { ans[l] = Max[o]; return; } int mid = l + r >> 1; Max[lo] = max(Max[lo], Max[o]); Max[ro] = max(Max[ro], Max[o]); pushdown(l, mid, lo); pushdown(mid + 1, r, ro); } int main() { while(~scanf("%d", &n)) { rep(i, 1, n + 1) scanf("%d", a + i); rep(i, 1, n + 1) { b[i].first = a[i]; b[i].second = i; } sort(b + 1, b + n + 1); mst(have, 0); build(1, n, 1); for(int i = n; i >= 1; i--) { ll v = b[i].first; int p = b[i].second; update(1, n, 1, 1, 1, v * v); head[p] = tail[p] = p; have[p] = 1; mx[p] = p; if(have[p - 1]) { head[p] = head[p - 1]; tail[head[p]] = p; int L = p + 1 - mx[head[p]]; int R = p + 1 - head[p]; if(have[p + 1]) R += tail[p + 1] - p; update(1, n, 1, L, R, v * a[mx[head[p]]]); } if(have[p + 1]) { int L = mx[p + 1] - p + 1; int R = tail[p + 1] - p + 1; if(have[p - 1]) R += p - head[p]; update(1, n, 1, L, R, v * a[mx[p + 1]]); tail[head[p]] = tail[p + 1]; head[tail[head[p]]] = head[p]; if(a[mx[p + 1]] > a[mx[head[p]]]) { mx[head[p]] = mx[p + 1]; } } } pushdown(1, n, 1); for(int i = 1; i <= n; i++) printf("%I64d\n", ans[i]); } return 0; } 
          
         
       
      
      
     
     
    
    
   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值