codeforces 1136E-Nastya Hasn't Written a Legend

传送门:QAQQAQ

题意:有一个数组a和一个数组k,数组a一直保持一个性质:a[i + 1] >= a[i] + k[i]。有两种操作:1,给某个元素加上x,但是加上之后要保持数组a的性质。比如a[i]加上x之后,a[i + 1]<a[i] + k[i],那么a[i + 1]就变成a[i] + k[i],否则不变。同理,若a[i + 2]小于了现在的a[i + 1] + k[i + 1],那么a[i + 2]也变成a[i + 1] + k[i + 1],一直保持这个性质。第二章操作,询问数组a的区间[l, r]的区间和。

思路:用另一个b数组保存a[i]-(k[1]+k[2]+...+k[i-1]),这样由题意的大小关系可知,b数组是非递减的。所以更新是只需在b[x]加上y用二分找出一段连续的需要被修改的区间即可,为节省时间,k应该用前缀和形式保存。

  查询时,只需利用b数组建造线段树并维护,求区间sum并加上之前每个b[i]被减掉的k即可,为节省时间,可以再前缀和k的基础上再加一个前缀和kk。这样查询时只需求query(1,1,n,l,r)+kk[r-1]-kk[l-2]。

注意:b数组只在建线段树时用到,因为后面b不再被更新,需要用query求出最新的b数组里的值; 赋值懒标记tag时一定要赋值成数据无法触碰到的值INF,否则会出现无法pushdown的情况(之前赋值成-1,在第7个点上调了老半天)。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 const int N=200001;
  5 const ll inf=-1e18;
  6
  7 ll n,a[N],b[N],k[N],kk[N],m;
  8
  9 ll sum[N<<2],tag[N<<2];
 10 void build(int x,int l,int r)
 11 {
 12     if(l==r)
 13     {
 14         sum[x]=b[l];
 15         return;
 16     }
 17     int mid=(l+r)>>1;
 18     build(x+x,l,mid);
 19     build(x+x+1,mid+1,r);
 20     sum[x]=sum[x+x]+sum[x+x+1];
 21 }
 22
 23 void push_down(int x,int l,int r)
 24 {
 25     int mid=(l+r)>>1;
 26     if(tag[x]==inf) return;
 27     tag[x+x]=tag[x]; tag[x+x+1]=tag[x];
 28     sum[x+x]=tag[x]*(mid-l+1);
 29     sum[x+x+1]=tag[x]*(r-mid);
 30     tag[x]=inf;
 31 }
 32
 33 void update(int x,int l,int r,int L,int R,ll val)
 34 {
 35     if(L<=l&&r<=R)
 36     {
 37         tag[x]=val;
 38         sum[x]=val*(r-l+1);
 39         return;
 40     }
 41     int mid=(l+r)>>1;
 42     push_down(x,l,r);
 43     if(mid>=R) update(x+x,l,mid,L,R,val);
 44     else if(mid<L) update(x+x+1,mid+1,r,L,R,val);
 45     else
 46     {
 47         update(x+x,l,mid,L,R,val);
 48         update(x+x+1,mid+1,r,L,R,val);
 49     }
 50     sum[x]=sum[x+x]+sum[x+x+1];
 51 }
 52
 53 ll query(int x,int l,int r,int L,int R)
 54 {
 55     if(L>R) return 0;
 56     if(L<=l&&r<=R) return sum[x];
 57     int mid=(l+r)>>1;
 58     push_down(x,l,r);
 59     if(mid>=R) return query(x+x,l,mid,L,R);
 60     else if(mid<L) return query(x+x+1,mid+1,r,L,R);
 61     else
 62     {
 63         return query(x+x,l,mid,L,R)+query(x+x+1,mid+1,r,L,R);
 64     }
 65 }
 66
 67 int main()
 68 {
 69     for(int i=0;i<(N<<2);i++) tag[i]=inf;
 70     scanf("%lld",&n);
 71     for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
 72     for(int i=1;i<n;i++) scanf("%lld",&k[i]);
 73     for(int i=2;i<n;i++) k[i]+=k[i-1];
 74     for(int i=1;i<n;i++) kk[i]=kk[i-1]+k[i];
 75     for(int i=1;i<=n;i++) b[i]=a[i]-k[i-1];//feidijian
 76     build(1,1,n);
 77     scanf("%lld",&m);
 78     while(m--)
 79     {
 80         char s[2]; int x,y;
 81         scanf("%s%d%d",s,&x,&y);
 82         if(s[0]==‘s‘)
 83         {
 84             ll add=kk[y-1]-(x>=2 ? kk[x-2] : 0);
 85             printf("%lld\n",add+query(1,1,n,x,y));
 86         }
 87         else
 88         {
 89             ll num=query(1,1,n,x,x)+y;//can‘t write b[x] instead of query(1,1,n,x,x)
 90             //int pos=lower_bound(b,b+n+1,num)-b;
 91             //can‘t use array b!
 92             int l=x,r=n,mid,pos=x;
 93             while(l<=r)
 94             {
 95                 mid=(l+r)>>1;
 96                 if(num>query(1,1,n,mid,mid))
 97                 {
 98                     pos=mid;
 99                     l=mid+1;
100                 }
101                 else r=mid-1;
102             }
103             update(1,1,n,x,pos,num);
104         }
105     }
106     return 0;
107 }

codeforces 1136E-Nastya Hasn't Written a Legend

原文地址:https://www.cnblogs.com/Forever-666/p/10740814.html

时间: 2024-08-30 17:57:53

codeforces 1136E-Nastya Hasn't Written a Legend的相关文章

Codeforces 1136E Nastya Hasn&#39;t Written a Legend (线段树教做人系列)

题意:有一个数组a和一个数组k,数组a一直保持一个性质:a[i + 1] >= a[i] + k[i].有两种操作:1,给某个元素加上x,但是加上之后要保持数组a的性质.比如a[i]加上x之后,a[i + 1]<a[i] + k[i],那么a[i + 1]就变成a[i] + k[i],否则不变.同理,若a[i + 2]小于了现在的a[i + 1] + k[i + 1],那么a[i + 2]也变成a[i + 1] + k[i + 1],一直保持这个性质.第二章操作,询问数组a的区间[l, r]的

Nastya Hasn&#39;t Written a Legend(Codeforces Round #546 (Div. 2)E+线段树)

题目链接 传送门 题面 题意 给你一个\(a\)数组和一个\(k\)数组,进行\(q\)次操作,操作分为两种: 将\(a_i\)增加\(x\),此时如果\(a_{i+1}<a_i+k_i\),那么就将\(a_{i+1}\)变成\(a_i+k_i\),如果\(a_{i+2}<a_i+k_i\),则将\(a_{i+2}\)变成\(a_{i+1}+k_{i+1}\),以此类推. 查询\(\sum\limits_{i=l}^{r}a_i\). 思路 我们首先存下\(k\)数组的前缀和\(sum1\),

[cf 1136] E. Nastya Hasn&#39;t Written a Legend

题意 给两个数组分别为\(a\)和\(k\),有若干次操作: 1.给\(a_x\)加上\(y\),并以此对\(a_{x + i}(i \ge 1)\)赋值为\(\max \{a_{x + i}, a_{x + i - 1} + k_{x + i - 1}\}\). 2.询问区间\([l, r]\)的\(a_i\)的和. 题解 自闭了啊. 考虑把原序列分成若干个块,对于每个块内必须满足,除最后一个位置的所有位置\(i\),\(a_i + k_i = a_i + 1\).刚开始可以看成有\(n\)个

CF1136E Nastya Hasn&#39;t Written a Legend(线段树)

还能说什么呢,简直太妙了. $$a_{i+1}<a_i+k_i$$ $$a_{i+1}-k_i-k_{i-1}-\cdots-k_1<a_i+k_i-k_i-k_{i-1}-\cdots-k_1$$ $$a_{i+1}-k_i-k_{i-1}-\cdots-k_1<a_i-k_{i-1}-\cdots-k_1$$ 令 $k$ 的前缀和为 $kpre$. $$a_{i+1}-kpre_i<a_i-kpre_{i-1}$$ 令 $b_i=a_i-kpre_{i-1}$. $$b_{i+

Codeforces 713C Sonya and Problem Wihtout a Legend(单调DP)

[题目链接] http://codeforces.com/problemset/problem/713/C [题目大意] 给出一个数列,请你经过调整使得其成为严格单调递增的数列,调整就是给某些位置加上或者减去某个数,调整的代价是加上或者减去的数的绝对值之和,请你输出最小代价. [题解] 先考虑这样一个问题,如果是非严格单调递增该如何做,我们会发现每次调整,都是调整某个数字为原先数列中存在的数字,最后才是最优的,所以,我们设DP[i][j]表示前i个数字,最后一个数为原先数列排序后第j大的数字的最

CodeForces 713C Sonya and Problem Wihtout a Legend

$dp$. 非严格递增的可以由$dp$解决.可以将严格递增转化为非严格递增. 要保证$a[i]<a[i+1]$,就是要保证$a[i]<=a[i+1]-1$,也就是$a[i]-i≤a[i+1]-1-i$,等价于$a[i]-i≤a[i+1]-(i+1)$. 因此只要将$a[i]-i$,求非严格递增的就可以了. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #inclu

@codeforces - [email&#160;protected] Vladislav and a Great Legend

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定一棵 n 个点的树 T.对于每一个非空点集 X,定义 f(X) 为包含 X 内所有点的最小连通块的边数. 另给定一正整数 k,求: \[\sum\limits_{X \subseteq \{1, 2,\: \dots \:, n\},\, X \neq \varnothing} (

Codeforces 992 E. Nastya and King-Shamans

\(>Codeforces\space992 E. Nastya and King-Shamans<\) 题目大意 : 给你一个长度为 \(n\) 的序列,有 \(q\) 次操作,每一次操作将一个数 \(A_i\) 改为另外一个数.每一次操作结束时,你需要找出一个位置 \(x\) 满足 \(A_x = sum_{x-1}\) 其中 \(sum\) 表示前缀和 $n , q \leq 2 \times 10^5   0 \leq A_i \leq 10^9 $ 解题思路 : 博主亲测分块加均摊分

Codeforces Round #546 (Div. 2) C. Nastya Is Transposing Matrices

C. Nastya Is Transposing Matrices time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Nastya came to her informatics lesson, and her teacher who is, by the way, a little bit famous here gave he