SPOJ DCEPC11I

题目大意:

就是给定一段区间令其中的数增加一个递增序列(也就是说第一个+1,第二个+2.。。。。)

询问操作是区间的和

这里的查询很简单,但是对于添加递增序列入区间就比较搞脑子了

我们需要一个add[]作为区间的首个数字增加的值,del[]表示等差数列的公差,因为你每次添加进入一个等差数列,是可以叠加的但公差变为了del[ls]+=del[o]

这里主要是pushdown函数的写法

我们要用到等差公式的求和:S =a*n+n(n-1)*d/2

void push_down(int o,int x,int y)
{
    int mid=(x+y)/2,ls=o<<1,rs=o<<1|1;
    if(add[o]||del[o]){
        int t1=mid-x+1,t2=y-mid;
        LL a2=add[o]+t1*del[o];
        sum[ls]+=add[o]*t1+t1*(t1-1)*del[o]/2;
        sum[rs]+=a2*t2+t2*(t2-1)*del[o]/2;
        add[ls]+=add[o],add[rs]+=a2;
        del[ls]+=del[o],del[rs]+=del[o];
        add[o]=del[o]=0;
    }
}

总代码如下所示:

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 #define L ls,x,mid
 5 #define R rs,mid+1,y
 6 #define LL long long
 7 #define N 100010
 8 LL sum[N<<2],add[N<<2];
 9 int del[N<<2];
10 void push_up(int o)
11 {
12     sum[o]=sum[o<<1]+sum[o<<1|1];
13 }
14 void push_down(int o,int x,int y)
15 {
16     int mid=(x+y)/2,ls=o<<1,rs=o<<1|1;
17     if(add[o]||del[o]){
18         int t1=mid-x+1,t2=y-mid;
19         LL a2=add[o]+t1*del[o];
20         sum[ls]+=add[o]*t1+t1*(t1-1)*del[o]/2;
21         sum[rs]+=a2*t2+t2*(t2-1)*del[o]/2;
22         add[ls]+=add[o],add[rs]+=a2;
23         del[ls]+=del[o],del[rs]+=del[o];
24         add[o]=del[o]=0;
25     }
26 }
27 void build(int o,int x,int y)
28 {
29     int mid=(x+y)/2,ls=o<<1,rs=o<<1|1;
30     sum[o]=del[o]=add[o]=0;
31     if(x==y) return;
32     build(L);
33     build(R);
34 }
35 void update(int o,int x,int y,int s,int t)
36 {
37     int mid=(x+y)/2,ls=o<<1,rs=o<<1|1;
38     if(x>=s&&y<=t){
39         add[o]+=x-s+1;
40         sum[o]+=(x-s+1)*(y-x+1)+(y-x+1)*(y-x)/2;
41         del[o]++;
42         return;
43     }
44     push_down(o,x,y);
45     if(mid>=s) update(L,s,t);
46     if(mid<t) update(R,s,t);
47     push_up(o);
48 }
49 void query(int o,int x,int y,int s,int t,LL &ans)
50 {
51     int mid=(x+y)/2,ls=o<<1,rs=o<<1|1;
52     if(x>=s&&y<=t){
53         ans+=sum[o];
54         return;
55     }
56     push_down(o,x,y);
57     if(mid>=s) query(L,s,t,ans);
58     if(mid<t) query(R,s,t,ans);
59 }
60 int main()
61 {
62     int n,q,op,a,b;
63     scanf("%d%d",&n,&q);
64     build(1,1,n);
65     for(int i=0;i<q;i++){
66         scanf("%d%d%d",&op,&a,&b);
67         if(op){
68             LL ans=0;
69             query(1,1,n,a,b,ans);
70             printf("%lld\n",ans);
71         }
72         else update(1,1,n,a,b);
73     }
74     return 0;
75 }

SPOJ DCEPC11I

时间: 2024-10-12 21:42:04

SPOJ DCEPC11I的相关文章

Problem B SPOJ DCEPC11I

Description Vaibhav Sir and Saikat Sir, after completing their graduation, got a job together at a store. Their boss at the store was Sidharth Sir, who was very strict and did not want anyone to have fun at the job. He gave Vaibhav and Saikat sir a v

CSU-ACM暑假集训基础组训练赛(4)解题报告

•Problem A SPOJ SUB_PROB   AC自动机 •题意: 给定一个长为M(M≤100000 )的文本串,和N(N≤1000)个长度不超过2000的模式串,问每个模式串是否在文本串中出现过? •几乎和周一课件上的第一个例题一模一样.. •把文本串丢到AC自动机里面去跑. •注意: •1.可能有两个相同的模式串(略坑吧.) •2.一个模式串可能是另一个模式串的后缀,即如果一个点的fail指针指向的点是一个“危险节点”,那么它本身也是一个“危险节点”. 1 #include <ios

SPOJ 705 Distinct Substrings(后缀数组)

[题目链接] http://www.spoj.com/problems/SUBST1/ [题目大意] 给出一个串,求出不相同的子串的个数. [题解] 对原串做一遍后缀数组,按照后缀的名次进行遍历, 每个后缀对答案的贡献为n-sa[i]+1-h[i], 因为排名相邻的后缀一定是公共前缀最长的, 那么就可以有效地通过LCP去除重复计算的子串. [代码] #include <cstdio> #include <cstring> #include <algorithm> usi

SPOJ 3273

传送门: 这是一道treap的模板题,不要问我为什么一直在写模板题 依旧只放代码 1 //SPOJ 3273 2 //by Cydiater 3 //2016.8.31 4 #include <iostream> 5 #include <cstring> 6 #include <ctime> 7 #include <cmath> 8 #include <cstdlib> 9 #include <string> 10 #include

SPOJ CRAN02 - Roommate Agreement

题目链接:http://www.spoj.com/problems/CRAN02/ 题目大意:N个数字组成的序列,和为0的连续子序列的个数.N<1e6 解题思路:计算前缀和,统计每个数字出现的次数,那么对于数字sum[i], 如果存在k个sum[i],则代表有C(k, 2)个序列和为0,而如果sum[i] = 0,则还要累加上对应的k值. 代码: 1 ll n; 2 int a[maxn]; 3 ll sum[maxn]; 4 map<int, int> mmp; 5 6 void so

spoj GCJ1C09C Bribe the Prisoners

题目链接: http://www.spoj.com/problems/GCJ1C09C/ 题意: In a kingdom there are prison cells (numbered 1 to P) built to form a straight line segment. Cells number i and i+1 are adjacent, and prisoners in adjacent cells are called "neighbours." A wall wi

SPOJ QTREE Query on a tree ——树链剖分 线段树

[题目分析] 垃圾vjudge又挂了. 树链剖分裸题. 垃圾spoj,交了好几次,基本没改动却过了. [代码](自带常数,是别人的2倍左右) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 20005 int T,n,fr[maxn],h[maxn],to[maxn],ne[maxn]

BZOJ 2588: Spoj 10628. Count on a tree 主席树+lca

2588: Spoj 10628. Count on a tree Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文. Input 第一行两个整数N,M. 第二行有N个整数,其中第i个整数表示点i的权值. 后面N-1行每行两个整数(x,y),表示点x到点y有一条边. 最后M行每行两个整数(u,v,k),表示一组询问.

BZOJ 1002 + SPOJ 104 基尔霍夫矩阵 + 一个递推式。

BZOJ 1002 高精度 + 递推 f[1] = 1; f[2] = 5; f[i] = f[i - 1] * 3 - f[i - 2] + 2; SPOJ 104 裸 + 不用Mod 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <algorithm> 5 #include <iostream> 6 7 using namespace std;