CDOJ 1292 卿学姐种花 暴力 分块 线段树
题目连接:
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 x y
表示卿学姐会在\(x\)号花坛种\(y\)朵花,并按相应的规律在后面的花坛上种花。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 | 1typedef 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);}elseprintf("%lld\n", seg.query(x));}return 0;
}
CDOJ 1292 卿学姐种花 暴力 分块 线段树相关推荐
- CDOJ 1292 卿学姐种花(暴力,分块,线段树)
众所周知,在喵哈哈村,有一个温柔善良的卿学姐. 卿学姐喜欢和她一样美丽的花.所以卿学姐家的后院有很多的花坛. 卿学姐有n 个花坛,一开始第 i个花坛里有 A[i] 朵花.每过一段时间,卿学姐都会在花坛 ...
- CDOJ 1292 卿学姐种花(分块)
题目链接:点击打开链接 思路: 由于是一个区间更新问题, 而且更新的值不一样, 所以我们考虑分块. 对于一个块, 我们维护第i块的第一个元素被加了多少了sum[i],第i块被更新了多少次cnt[i] ...
- 卿学姐与公主(线段树区间求最大值)
A - 卿学姐与公主 Time Limit: 2000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submi ...
- 卿学姐种花(线段树)
卿学姐种花 Time Limit: 0/7500MS (Java/Others) Memory Limit: 0/220000KB (Java/Others) 众所周知,在喵哈哈村,有一个温柔 ...
- cdoj 1328 卿学姐与诡异村庄 Label:并查集 || 二分图染色
卿学姐与诡异村庄 Time Limit: 4500/1500MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit ...
- 2016 UESTC Training for Data Structures O - 卿学姐种美丽的花 树状数组+等差数列
O - 卿学姐种美丽的花 Time Limit: 8000/4000MS (Java/Others) Memory Limit: 125535/65535KB (Java/Others) Su ...
- CDOJ1324-卿学姐与公主 【线段树点更新】
http://acm.uestc.edu.cn/#/problem/show/1324 卿学姐与公主 Time Limit: 2000/1000MS (Java/Others) Memory ...
- Acwing 4339 敌兵布阵 暴力 + 分块 + 线段树 + Zkw线段树 + 树状数组
来一篇超全题解 数据结构大杂烩 原题连接 题目描述 敌人有 NNN 个工兵营地,编号 1∼N1∼N1∼N. 初始时,第 iii 个营地有 aia_iai 个人. 接下来有若干个命令,命令有 444 ...
- CDOJ 1281 暴兵的卿学姐 构造题
暴兵的卿学姐 题目连接: http://acm.uestc.edu.cn/#/problem/show/1281 Description 沈宝宝又和卿学姐开始玩SC2了! 自从沈宝宝学会新的阵型后,就 ...
最新文章
- IOS/Android模拟器运行APP调试方法
- C++ Primer 5th笔记(chap 13 拷贝控制)阻止拷贝
- NSIS修改开始菜单中图标
- STL常用的算术和生成算法
- 话里话外:“按单制造”的业务特点(一)
- mybatis 中 Example 的使用 :条件查询、排序、分页(三种分页方式 : RowBounds、PageHelpler 、limit )
- windows端口备忘
- java Redis Jedis存储Java对象 - (Java序列化为byte数组方式)
- 程序员面试金典——5.8像素设定
- 烽火狼烟丨Microsoft多个安全漏洞风险提示
- BP神经网络时间序列预测-附代码
- windows 控制台cmd乱码的解决办法
- matlab 矩阵求和计算
- 位图深度 PIL.image.save()保存图片后size变大
- 改写二分搜索算法C++
- Web浏览过程中涉及到的协议
- VMware VCP认证常见问答题
- 自学闲置电脑部署NAS服务器打造家庭影院
- HTTP 提交方式有哪些
- 多元线性回归系数求解