bzoj 4127 线段树维护绝对值之和

 

因为d>=0,所以一个位置的数只会单调不降并且只会有一次穿过0.

用这个性质,我们我可在线段树中记录正数负数的个数和和,以及最大的负数以及答案.

修改操作:如果当前最大负数+d<=0,那么就直接加到懒惰标记中,否则就暴力向下传递.

因为每个节点最多被额外访问该区间负数个数次,所以所有点总共会被额外访问O(nlogn)次,在加上修改操作和询问操作的普通访问O(mlogn)次,所以时间复杂度是有保证的.

谢谢mhy12345的讲解.

 

  1 /**************************************************************
  2     Problem: 4127
  3     User: idy002
  4     Language: C++
  5     Result: Accepted
  6     Time:7872 ms
  7     Memory:49256 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <vector>
 12 #include <algorithm>
 13 #define min(a,b) ((a)<(b)?(a):(b))
 14 #define max(a,b) ((a)>(b)?(a):(b))
 15 #define abs(a) ((a)<0?-(a):(a))
 16 #define oo 0x3f3f3f3f3f3f3f3fLL
 17 #define N 200010
 18 //#define fprintf(...)
 19 using namespace std;
 20  
 21 typedef long long dnt;
 22  
 23 void getn( int &v ) {
 24     char ch=getchar();
 25     bool neg = false;
 26     while( ch!='-' && (ch<'0' || ch>'9') ) ch=getchar();
 27     if( ch=='-' ) {
 28         neg = true;
 29         ch = getchar();
 30     }
 31     v = ch-'0';
 32     ch = getchar();
 33     while( '0'<=ch && ch<='9' ) {
 34         v = v*10+ch-'0';
 35         ch = getchar();
 36     }
 37     if( neg ) v=-v;
 38 }
 39  
 40 struct Node {
 41     dnt ans, sum[2], cnt[2], nmx, tag;
 42     Node *ls, *rs;
 43     inline void init( int v ) {
 44         if( v<0 ) {
 45             sum[0] = v;
 46             cnt[0] = 1;
 47             sum[1] = 0;
 48             cnt[1] = 0;
 49             ans = -v;
 50             tag = 0;
 51             nmx = v;
 52         } else {
 53             sum[0] = 0;
 54             cnt[0] = 0;
 55             sum[1] = v;
 56             cnt[1] = 1;
 57             tag = 0;
 58             ans = v;
 59             nmx = -oo;
 60         }
 61     }
 62     inline void update() {
 63         sum[0] = ls->sum[0] + rs->sum[0];
 64         sum[1] = ls->sum[1] + rs->sum[1];
 65         cnt[0] = ls->cnt[0] + rs->cnt[0];
 66         cnt[1] = ls->cnt[1] + rs->cnt[1];
 67         ans = ls->ans + rs->ans;
 68         nmx = max( ls->nmx, rs->nmx );
 69     }
 70     inline void pushdown() {
 71         if( tag ) {
 72             ls->nmx += tag;
 73             rs->nmx += tag;
 74             ls->sum[0] += ls->cnt[0]*tag;
 75             ls->sum[1] += ls->cnt[1]*tag;
 76             rs->sum[0] += rs->cnt[0]*tag;
 77             rs->sum[1] += rs->cnt[1]*tag;
 78             ls->ans = ls->sum[1]-ls->sum[0];
 79             rs->ans = rs->sum[1]-rs->sum[0];
 80             ls->tag += tag;
 81             rs->tag += tag;
 82             tag = 0;
 83         }
 84     }
 85     void modify( int lf, int rg, int L, int R, int delta ) {
 86         if( lf==rg ) {
 87             if( cnt[0] ) {
 88                 if( sum[0]+delta<=0 ) {
 89                     sum[0]+=delta;
 90                     nmx = sum[0];
 91                     ans = -sum[0];
 92                 } else {
 93                     sum[1] = sum[0]+delta;
 94                     ans = sum[1];
 95                     cnt[1] = 1;
 96                     sum[0] = cnt[0] = 0;
 97                     nmx = -oo;
 98                 }
 99             } else {
100                 sum[1]+=delta;
101                 ans = sum[1];
102             }
103             return;
104         }
105         if( L<=lf && rg<=R && nmx+delta<=0 ) {
106             nmx += delta;
107             sum[0] += cnt[0]*delta;
108             sum[1] += cnt[1]*delta;
109             ans = sum[1]-sum[0];
110             tag += delta;
111             return;
112         }
113         pushdown();
114         int mid=(lf+rg)>>1;
115         if( L<=mid ) ls->modify(lf,mid,L,R,delta);
116         if( R>mid ) rs->modify(mid+1,rg,L,R,delta);
117         update();
118     }
119     dnt query( int lf, int rg, int L, int R ) {
120         if( L<=lf && rg<=R ) return ans;
121         pushdown();
122         int mid=(lf+rg)>>1;
123         dnt rt = 0;
124         if( L<=mid ) rt+=ls->query(lf,mid,L,R);
125         if( R>mid ) rt+=rs->query(mid+1,rg,L,R);
126         update();
127         return rt;
128     }
129 }pool[N*3], *tail=pool, *root;
130  
131 int n, m;
132 int aa[N], bb[N];
133 int head[N], dest[N<<1], next[N<<1], etot;
134 int fat[N], siz[N], son[N], top[N], dep[N], vid[N], qu[N], bg, ed;
135  
136 void adde( int u, int v ) {
137     etot++;
138     dest[etot] = v;
139     next[etot] = head[u];
140     head[u] = etot;
141 }
142 Node *build( int lf, int rg ) {
143     Node *nd = ++tail;
144     if( lf==rg) {
145         nd->init(bb[lf]);
146         return nd;
147     }
148     int mid=(lf+rg)>>1;
149     nd->ls = build( lf, mid );
150     nd->rs = build( mid+1, rg );
151     nd->update();
152     return nd;
153 }
154 void build_dcp( int s ) {
155     //  fat dep
156     fat[s] = 0;
157     dep[s] = 1;
158     qu[bg=ed=1] = s;
159     while( bg<=ed ) {
160         int u=qu[bg++];
161         for( int t=head[u]; t; t=next[t] ) {
162             int v=dest[t];
163             if( v==fat[u] ) continue;
164             fat[v] = u;
165             dep[v] = dep[u]+1;
166             qu[++ed] = v;
167         }
168     }
169     //  siz son
170     for( int i=ed; i>=1; i-- ) {
171         int u=qu[i], p=fat[u];
172         siz[u]++;
173         if( p ) {
174             siz[p] += siz[u];
175             if( siz[son[p]]<siz[u] ) son[p]=u;
176         }
177     }
178     //  vid top
179     vid[s] = 1;
180     top[s] = s;
181     for( int i=1; i<=ed; i++ ) {
182         int u=qu[i];
183         int cur=vid[u]+1;
184         if( son[u] ) {
185             vid[son[u]] = cur;
186             top[son[u]] = top[u];
187             cur += siz[son[u]];
188         }
189         for( int t=head[u]; t; t=next[t] ) {
190             int v=dest[t];
191             if( v==fat[u] || v==son[u] ) continue;
192             vid[v] = cur;
193             top[v] = v;
194             cur += siz[v];
195         }
196     }
197     //  segment tree
198     for( int i=1; i<=n; i++ ) 
199         bb[vid[i]] = aa[i];
200 //  for( int i=1; i<=n; i++ )
201 //      fprintf( stderr, "%d ", bb[i] );
202 //  fprintf( stderr, "\n" );
203     root = build( 1, n );
204 }
205 void modify( int u, int v, int delta ) {
206     while( top[u]!=top[v] ) {
207         if( dep[top[u]]<dep[top[v]] ) swap(u,v);
208         root->modify(1,n,vid[top[u]],vid[u],delta);
209 //      fprintf( stderr, "modify( %d %d %d )\n", vid[top[u]], vid[u], delta );
210         u=fat[top[u]];
211     }
212     if( dep[u]<dep[v] ) swap(u,v);
213     root->modify(1,n,vid[v],vid[u],delta);
214 //  fprintf( stderr, "modify( %d %d %d )\n", vid[v], vid[u], delta );
215 }
216 dnt query( int u, int v ) {
217     dnt rt = 0;
218     while( top[u]!=top[v] ) {
219         if( dep[top[u]]<dep[top[v]] ) swap(u,v);
220         rt += root->query(1,n,vid[top[u]],vid[u]);
221 //      fprintf( stderr, "query( %d %d ) rt = %lld\n", vid[top[u]], vid[u], rt );
222         u=fat[top[u]];
223     }
224     if( dep[u]<dep[v] ) swap(u,v);
225     rt += root->query(1,n,vid[v],vid[u]);
226 //  fprintf( stderr, "query( %d %d ) rt = %lld\n", vid[v], vid[u], rt );
227     return rt;
228 }
229 int main() {
230     getn(n); getn(m);
231     for( int i=1; i<=n; i++ )
232         getn(aa[i]);
233     for( int i=1,u,v; i<n; i++ ) {
234         getn(u); getn(v);
235         adde( u, v );
236         adde( v, u );
237     }
238     build_dcp(1);
239     for( int t=1,opt,u,v,d; t<=m; t++ ) {
240         getn(opt);
241         if( opt==1 ) {
242             getn(u);getn(v);getn(d);
243             modify( u, v, d );
244         } else {
245             getn(u); getn(v);
246             printf( "%lld\n", query(u,v) );
247         }
248     }
249 }
View Code

 

转载于:https://www.cnblogs.com/idy002/p/4558469.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值