卿学姐种花

题目连接:

http://acm.uestc.edu.cn/#/problem/show/1292

Description

众所周知,在喵哈哈村,有一个温柔善良的卿学姐。

卿学姐喜欢和她一样美丽的花。所以卿学姐家的后院有很多的花坛。

卿学姐有\(n\)个花坛,一开始第\(i\)个花坛里有\(A[i]\)朵花。每过一段时间,卿学姐都会在花坛里种上新的花。

作为一个聪明的学姐,卿学姐的种花方式也是与众不同 , 每一次,卿学姐会在第\(x\)个花坛种上\(y\)朵花,然后在第\(x+1\)个花坛上种上\(y-1\)朵花,再在第\(x+2\)个花坛上种上\(y-2\)朵花......以此类推,直到种到最后一个花坛,或者不需要种花为止。

喵哈哈的村民们都喜欢去卿学姐的后院赏花,沈宝宝也不例外。然而沈宝宝可不是省油的灯,怎么可能会老老实实地赏花呢。每次沈宝宝来时,都会随机询问卿学姐在第\(i\)个花坛有多少朵花。

花坛的花实在太多了,卿学姐实在是数不过来。于是现在她向你求助,希望你能帮她数出花坛里多少朵花。

Input

第一行输入两个整数,花坛个数\(N\)和操作次数\(Q\)。

第二行\(N\)个整数\(A[1],A[2],A[3].....A[N]\)。 ( $1 \leq A[i] \leq 2^{31} $ )

接下来\(Q\)行,每行一个操作。

  1. 1 x y 表示卿学姐会在\(x\)号花坛种\(y\)朵花,并按相应的规律在后面的花坛上种花。

  2. 2 x 表示沈宝宝问卿学姐第\(x\)个花坛有多少朵花。

数据保证:

  • $1 \leq N \leq 10^4 $

  • $1 \leq Q \leq {2*10^6} $

  • $\sum x \leq 10^8 \(,\)x$代表操作 \(2\) 的询问下标

  • 对于操作 $ 1 $ , \(1 \leq x \leq N\),\(1 \leq y \leq 10^9\)

  • 对于操作 $ 2 $ , \(1 \leq x \leq N\)

Output

对于每个询问操作,按顺序输出答案对\(772002 + 233\)取模的值。

Sample Input

6 3

1 2 3 2 1 2

1 2 3

2 3

2 6

Sample Output

5

2

Hint

题意

题解:

最简单的方法,O(N)去更新,然后O(1)去查询就好了,但是显然这样子会TLE的

然后我们注意,我们发现这道保证查询操作的sigmax<=1e8

所以我们把这个变成O(1)更新,O(N)查询就好了,这个东西打个延时标记就好了。

比如1 x y

我只需要使得lazy[x]+=y,表示x这个位置需要往下更新的大小增加y

ed[x+y]++,表示某一个更新会在x+y这个位置停止。

num[x]++,表示x这个位置多了一个更新。

然后我们查询2 x的时候

我们只需要从1这个位置,一直for到x这个位置就好了,然后处理我们刚才打上去的延迟标记。

add表示现在累计了多少的值,Num表示现在我有多少个更新。

add+=lazy[i],

Num+=num[i],Num-=ed[i]。

a[i] = (a[i]+add)%mod;

add-=Num。显然走一步,就会减少Num

然后就完了~

然后有人会深入去思考,假设没有那个 sigma x<=1e8怎么办?

其实查询和更新均摊一下就好了:

有两种,

1.分块,这个方法可以把查询和更新操作都均摊到O(sqrt(n)),直接暴力更新这个值在这个块内的数据,然后再暴力更新其他大块就好了

2.线段树,直接暴力去怼线段树就好了

下面是代码:

正解大暴力

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4+5;
const int mod = 772002+233; long long a[maxn],lazy[maxn],num[maxn],ed[maxn];
int n,m;
void updata(int x,long long y)
{
lazy[x]+=y;
num[x]++;
ed[min(1ll*n+1,x+y)]++;
}
long long query(int x)
{
long long add = 0;
long long Num = 0;
for(int i=1;i<=x;i++)
{
add+=lazy[i];
Num+=num[i];
Num-=ed[i];
lazy[i]=num[i]=ed[i]=0;
a[i]=(a[i]+add)%mod;
add-=Num;
}
lazy[x+1]+=add,num[x+1]+=Num;
return a[x];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]),a[i]%=mod;
for(int i=1;i<=m;i++)
{
int op,x;
long long y;
scanf("%d",&op);
if(op==1)
{
scanf("%d%lld",&x,&y);
updata(x,y);
}
else
{
scanf("%d",&x);
printf("%lld\n",query(x));
}
}
}

迷之分块

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
const int mod = 772002+233;
long long a[maxn];
int l[1000],r[1000];
int block,num,belong[maxn];
long long lazy[maxn],number[maxn],ed[maxn];
int n,m;
void updata(int x,long long y)
{
for(int i=x;i<=r[belong[x]];i++)
{
a[i]=(a[i]+y)%mod;
y--;if(y==0)return;
}
for(int i=belong[x]+1;i<=num;i++)
{
lazy[l[i]]+=y;
number[l[i]]++;
if(y<(r[i]-l[i]+1))
{
ed[l[i]+y]++;
break;
}
y-=(r[i]-l[i]+1);
}
}
long long query(int x)
{
long long add = 0;
long long Num = 0;
for(int i=l[belong[x]];i<=r[belong[x]];i++)
{
add+=lazy[i];
Num+=number[i];
Num-=ed[i];
lazy[i]=number[i]=ed[i]=0;
a[i]=(a[i]+add)%mod;
add-=Num;
}
return a[x]%mod;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]),a[i]%=mod;;
block=(int)sqrt(n+0.5);
num = n/block;
if(n%block)num++;
for(int i=1;i<=num;i++)
l[i]=(i-1)*block+1,r[i]=i*block;
r[num]=n; for(int i=1;i<=n;i++)
belong[i]=(i-1)/block+1; for(int i=1;i<=m;i++)
{
int op,x,y;
scanf("%d",&op);
if(op==1)
{
scanf("%d%lld",&x,&y);
updata(x,y);
}
else
{
scanf("%d",&x);
printf("%lld\n",query(x));
}
}
}

线段树(1)

#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define lid (id << 1)
#define rid (id << 1 | 1)
using namespace std;
typedef long long LL;
const int N = 1e4 + 10;
const LL MOD = 772002 + 233; int n,q;
LL a[N];
struct Segtree{
int l,r;
LL time,cnt;
}tr[N * 4]; void Segtree_Initial(int id,int l,int r)
{
tr[id].l = l;
tr[id].r = r;
tr[id].time = tr[id].cnt = 0;
if(l != r)
{
int mid = (l + r) >> 1;
Segtree_Initial(lid,l,mid);
Segtree_Initial(rid,mid + 1,r);
}
} void Segtree_Update(int id,int l,int r,LL x)
{
if(l > r) return;
if(tr[id].l == l && tr[id].r == r)
{
tr[id].time++;
tr[id].cnt += x;
return;
} int mid = (tr[id].l + tr[id].r) >> 1 ;
Segtree_Update(lid,l,min(mid , r),x);
Segtree_Update(rid,max(l , mid + 1),r,x - max(mid + 1 - l , 0) );
} LL Segtree_Query(int id,int pos)
{
if(tr[id].l > pos || tr[id].r < pos) return 0; LL tot = tr[id].cnt - (1LL * (pos - tr[id].l) * 1LL) * tr[id].time; if(tr[id].l != tr[id].r) tot += Segtree_Query(lid,pos) + Segtree_Query(rid,pos);
return tot;
} void init()
{
scanf("%d%d",&n,&q);
for(int i = 1;i <= n;i++)
scanf("%lld",&a[i]);
Segtree_Initial(1,1,n);
} void work()
{
int s,pos,x,l,r;
LL y,ans;
for(int i = 1;i <= q;i++)
{
scanf("%d",&s);
if(s == 1)
{
scanf("%d%lld",&x,&y);
l = x,r = x + int(y) - 1;
if(r >= n) r = n;
Segtree_Update(1,l,r,y);
}
else
{
scanf("%d",&pos);
ans = (Segtree_Query(1,pos) + a[pos]) % MOD;
printf("%lld\n",ans);
}
}
} int main()
{
init();
work();
}

线段树(2)

#include <cstdio>

#define MAX_N 10004
#define lchild l, m, v << 1
#define rchild m + 1, r, v << 1 | 1 typedef long long ll; int N, Q;
ll A[MAX_N]; const ll mod = 772002 + 233; void add(ll &x, ll a){
x = (x + a) % mod;
} struct SegmentTree{
struct node{
ll coverTime;
ll headNum;
}tree[MAX_N * 4]; SegmentTree();
void build(int, int, int);
void pushDown(int, int, int);
void update(int, int, ll, int, int, int);
ll query(int, int, int, int);
}seg; SegmentTree::SegmentTree(){
for(int i = 0; i < MAX_N * 4; i++)
tree[i].coverTime = tree[i].headNum = 0;
} void SegmentTree::build(int l = 1,int r = N, int v = 1){
if(l == r){
tree[v].headNum = A[l];
return;
}
int m = (l + r) >> 1;
build(lchild);
build(rchild);
} void SegmentTree::pushDown(int l, int r, int v){
int m = (l + r) >> 1;
add(tree[v << 1].coverTime, tree[v].coverTime);
add(tree[v << 1 | 1].coverTime, tree[v].coverTime);
add(tree[v << 1].headNum, tree[v].headNum);
add(tree[v << 1 | 1].headNum, (tree[v].headNum - (m - l + 1) * tree[v].coverTime % mod) % mod);
tree[v].coverTime = tree[v].headNum = 0;
} void SegmentTree::update(int L, int R, ll x, int l = 1, int r = N, int v = 1){
if(L <= l && r <= R){
add(tree[v].headNum, x - (l - L));
add(tree[v].coverTime, 1);
return;
}
if(tree[v].coverTime) pushDown(l, r, v);
int m = (l + r) >> 1;
if(L <= m) SegmentTree::update(L, R, x, lchild);
if(R > m) SegmentTree::update(L, R, x, rchild);
} ll SegmentTree::query(int a, int l = 1, int r = N, int v = 1){
if(l == r)
return (tree[v].headNum %mod + mod) % mod;
if(tree[v].coverTime) pushDown(l, r, v);
int m = (l + r) >> 1;
if(a <= m) return SegmentTree::query(a, lchild);
else return SegmentTree::query(a, rchild);
} int main(){
scanf("%d%d", &N, &Q);
for(int i = 1; i <= N; i++)
scanf("%lld", &A[i]);
seg.build();
while(Q--){
int op, x, y;
scanf("%d%d", &op, &x);
if(op == 1){
scanf("%d", &y);
int z = x + y - 1 > N ? N : x + y - 1;
seg.update(x, z, y);
}
else
printf("%lld\n", seg.query(x));
}
return 0;
}

CDOJ 1292 卿学姐种花 暴力 分块 线段树的更多相关文章

  1. CDOJ 1324 卿学姐与公主 分块

    题目地址 分块模板 #include<cstdio> #include<algorithm> #include<math.h> using namespace st ...

  2. CDOJ 1324 卿学姐与公主(分块)

    CDOJ 1324 卿学姐与公主(分块) 传送门: UESTC Online Judgehttp://acm.uestc.edu.cn/#/problem/show/1324 某日,百无聊赖的卿学姐打 ...

  3. cdoj 1328 卿学姐与诡异村庄 Label:并查集 || 二分图染色

    卿学姐与诡异村庄 Time Limit: 4500/1500MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit  ...

  4. cdoj 1329 卿学姐与魔法 优先队列

    卿学姐与魔法 Time Limit: 1200/800MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit Sta ...

  5. cdoj 1324 卿学姐与公主 线段树裸题

    卿学姐与公主 Time Limit: 2000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit St ...

  6. E - 卿学姐与城堡的墙(树状数组求逆序数)

    卿学姐与城堡的墙 Time Limit: 2000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit  ...

  7. CDOJ1324-卿学姐与公主 【线段树点更新】

    http://acm.uestc.edu.cn/#/problem/show/1324 卿学姐与公主 Time Limit: 2000/1000MS (Java/Others)     Memory ...

  8. UESTC 1324 卿学姐与公主 分块板子

    #include<iostream> #include<cmath> using namespace std; ; //表示当前数在哪一块里面 int belong[maxn] ...

  9. UESTC 1324:卿学姐与公主(分块)

    http://acm.uestc.edu.cn/#/problem/show/1324 题意:…… 思路:卿学姐的学习分块例题. 分块是在线处理区间问题的类暴力算法,复杂度O(n*sqrt(n)),把 ...

随机推荐

  1. [转载]Android中Bitmap和Drawable

    一.相关概念 1.Drawable就是一个可画的对象,其可能是一张位图(BitmapDrawable),也可能是一个图形(ShapeDrawable),还有可能是一个图层(LayerDrawable) ...

  2. 全局应用程序类(Global.asax)

     注:该部分参考的园区的“积少成多”的 <ASP.NET MVC中的Global.asax文件> . 1.Global.asax文件介绍 global.asax这个文件包含全局应用程序事件 ...

  3. 修改vs17中的cordova模板

    因为visual studio 2017创建的默认cordova-ios的版本自动编译带有swift语言的插件会出现异常,cordova-ios升级到4.3.1,并且配置build.json能解决问题 ...

  4. 5、SourceTree使用git

    1.拉取分支 拉去分支请参见:3.SourceTree通过PUTTY连接GitLab 最后内容 注:如果拉取后看不见master,请在gitLab页面的master上新建一个文件即可. 2.创建一个分 ...

  5. email的传输协议与格式(资源链接)

    以下链接为转载. 传输协议: 发:SMTP 收:POP3, IMAP 格式: MIME

  6. **CodeIgniter系列 添加filter和helper

    filter: 使用CI的hooks来实现filter. 1.在system/application/config/config.php中,把enable_hooks的值改为TRUE $config[ ...

  7. 【58沈剑架构系列】DB主从一致性架构优化4种方法

    需求缘起 大部分互联网的业务都是“读多写少”的场景,数据库层面,读性能往往成为瓶颈.如下图:业界通常采用“一主多从,读写分离,冗余多个读库”的数据库架构来提升数据库的读性能. 这种架构的一个潜在缺点是 ...

  8. AC日记——#2054. 「TJOI / HEOI2016」树

    #2054. 「TJOI / HEOI2016」树 思路: 线段树: 代码: #include <cstdio> #include <cstring> #include < ...

  9. [实战]MVC5+EF6+MySql企业网盘实战(6)——ajax方式登录

    写在前面 今天回来的比较早,就趁着有空,把登录的代码更新一下.上篇文章实现了ajax的注册,这篇将实现登录,实现目标,ajax登录方式,如果勾选记住我,则下次不再输入用户名密码,直接跳转到网盘界面. ...

  10. 微信小程序之wepy自动化架构搭建(fly+wepy-plugin-replace)

    前言 本文章秉着自动化工程项目的思想搭建的,基础架子完全按照wepy官网搭建,在基础上增加配置达到自动化项目.新增动flxio拦截器自动处理接口,新增根据环境变量来改变运行时的参数. Fly.js 小 ...