线段树
来源:互联网 发布:最新php视频 编辑:程序博客网 时间:2024/06/07 16:48
An easy problem B
N个数排成一列,每个数的大小为1或者0。有两种操作,第一种操作是把一段区间内的每个数异或1,第二种操作是询问区间内最长连续1的长度。
Input
第一行一个整数N(1≤N≤100000),表示N个数。第二行N个数。接下来一行一个整数M(1≤M≤100000),表示M个操作,接下来M行每行三个整数K,L,R。K=1表示把L到R这段区间的数全部异或上1,K=0表示询问L到R这段区间内最长连续1的长度。
Output
对于每个询问,输出对应的答案,每个询问占一行。
Sample Input
50 1 0 0 150 1 41 1 10 1 41 3 40 1 4
Sample Output
124
#include<cstdio>#include<algorithm>using namespace std;const int maxn = 1e5 + 5;struct node { int l, r, ll[2], rr[2], ans[2], flag;}tree[4 * maxn];void pushup(int rt){ int len = tree[rt].r - tree[rt].l + 1; for (int cur = 0; cur<2; cur++) { tree[rt].ll[cur] = tree[rt << 1].ll[cur]; tree[rt].rr[cur] = tree[rt << 1 | 1].rr[cur]; if (tree[rt << 1].ll[cur] == len - len / 2) tree[rt].ll[cur] += tree[rt << 1 | 1].ll[cur]; if (tree[rt << 1 | 1].rr[cur] == len / 2) tree[rt].rr[cur] += tree[rt << 1].rr[cur]; tree[rt].ans[cur] = max(max(tree[rt << 1].ans[cur], tree[rt << 1 | 1].ans[cur]), tree[rt << 1].rr[cur] + tree[rt << 1 | 1].ll[cur]); }}void pushdown(int rt){ if (tree[rt].flag) { swap(tree[rt << 1].ll[0], tree[rt << 1].ll[1]); swap(tree[rt << 1].rr[0], tree[rt << 1].rr[1]); swap(tree[rt << 1].ans[0], tree[rt << 1].ans[1]); swap(tree[rt << 1 | 1].ll[0], tree[rt << 1 | 1].ll[1]); swap(tree[rt << 1 | 1].rr[0], tree[rt << 1 | 1].rr[1]); swap(tree[rt << 1 | 1].ans[0], tree[rt << 1 | 1].ans[1]); tree[rt << 1].flag ^= tree[rt].flag; tree[rt << 1 | 1].flag ^= tree[rt].flag; tree[rt].flag = 0; }}void build(int l, int r, int rt){ tree[rt].l = l, tree[rt].r = r; tree[rt].flag = 0; if (l == r) { int x; scanf("%d", &x); tree[rt].ll[0] = tree[rt].rr[0] = tree[rt].ans[0] = (x == 0); tree[rt].ll[1] = tree[rt].rr[1] = tree[rt].ans[1] = (x == 1); return; } int mid = tree[rt].l + tree[rt].r >> 1; build(l, mid, rt << 1); build(mid + 1, r, rt << 1 | 1); pushup(rt);}void work(int l, int r, int rt){ if (l <= tree[rt].l&&r >= tree[rt].r) { tree[rt].flag ^= 1; swap(tree[rt].ll[0], tree[rt].ll[1]); swap(tree[rt].rr[0], tree[rt].rr[1]); swap(tree[rt].ans[0], tree[rt].ans[1]); return; } pushdown(rt); int mid = tree[rt].l + tree[rt].r >> 1; if (r <= mid) work(l, r, rt << 1); else if (l>mid) work(l, r, rt << 1 | 1); else { work(l, mid, rt << 1); work(mid + 1, r, rt << 1 | 1); } pushup(rt);}int query(int l, int r, int rt){ if (l <= tree[rt].l&&r >= tree[rt].r) return tree[rt].ans[1]; pushdown(rt); int mid = tree[rt].l + tree[rt].r >> 1; if (r <= mid) return query(l, r, rt << 1); else if (l>mid) return query(l, r, rt << 1 | 1); else { return max(min(tree[rt << 1].rr[1], mid - l + 1) + min(tree[rt << 1 | 1].ll[1], r - mid), max(query(l, mid, rt << 1), query(mid + 1, r, rt << 1 | 1))); //这里要考虑区间的大小和连续1的大小 }}int main(){ int m, n; scanf("%d", &n) ; build(1, n, 1); scanf("%d", &m); for (int i = 1; i <= m; i++) { int k, l, r; scanf("%d%d%d", &k, &l, &r); if (k == 1) { work(l, r, 1); } else { int ans = query(l, r, 1); printf("%d\n", ans); } } return 0;}
An easy problem C
N个数排成一列,有三种操作。1.给一段区间内的每个数乘上一个非负整数。2.给一段区间内的每个数加上一个非负整数.3.询问一段区间的和模上P的值。
Input
第一行两个整数N(1≤N≤100000)表示数的个数,P(1≤P≤1000000000)表示模的值。接下来一行N个整数ai(0≤ai≤1000000000),接下来一行一个整数M(1≤M≤100000)表示操作数量,接下来M行每行描述一个操作。第一种操作描述:1 L R C(0≤C≤1000000000),表示把L到R这段区间每个数乘上一个C。第二种操作描述:2 L R C(0≤C≤1000000000),表示把L到R这段区间每个数加上一个C。第三种操作3 L R 表示询问L到R这段区间内的数的和模上P的值。
Output
对面每个询问,输出对应的答案,每个询问占一行。
Sample Input
7 431 2 3 4 5 6 751 2 5 53 2 42 3 7 93 1 33 4 7
Sample Output
2358
#include<cstdio>#include<algorithm>using namespace std;typedef long long LL;const int maxn=1e5+5;LL sum[maxn*4],mul[maxn*4],add[maxn*4];LL n,mod,m;void pushup(int rt){ sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%mod;}void pushdown(int L,int R,int rt){ if(mul[rt]==1&&add[rt]==0) return; mul[rt<<1]=mul[rt<<1]*mul[rt]%mod; mul[rt<<1|1]=mul[rt<<1|1]*mul[rt]%mod; add[rt<<1]=(add[rt<<1]*mul[rt]%mod+add[rt])%mod; add[rt<<1|1]=(add[rt<<1|1]*mul[rt]%mod+add[rt])%mod; int len=R-L+1; sum[rt<<1]=(sum[rt<<1]*mul[rt]%mod+add[rt]*(LL)(len-len/2)%mod)%mod; sum[rt<<1|1]=(sum[rt<<1|1]*mul[rt]%mod+add[rt]*(LL)(len/2)%mod)%mod; mul[rt]=1; add[rt]=0;}void update(int l,int r,int L,int R,int rt,int x,int op){ if(l==L&&r==R){ if(op==1){ mul[rt]=mul[rt]*(LL)x%mod; add[rt]=add[rt]*(LL)x%mod; sum[rt]=sum[rt]*(LL)x%mod; }else{ add[rt]=(add[rt]+(LL)x)%mod; sum[rt]=(sum[rt]+(LL)(R-L+1)*x%mod)%mod; } return; } pushdown(L,R,rt); int mid=L+R>>1; if(r<=mid) update(l,r,L,mid,rt<<1,x,op); else if(l>mid) update(l,r,mid+1,R,rt<<1|1,x,op); else{ update(l,mid,L,mid,rt<<1,x,op); update(mid+1,r,mid+1,R,rt<<1|1,x,op); } pushup(rt);}void build(int L,int R,int rt){ add[rt]=0;mul[rt]=1; if(L==R){ scanf("%lld",&sum[rt]); sum[rt]%=mod; return; } int mid=L+R>>1; build(L,mid,rt<<1); build(mid+1,R,rt<<1|1); pushup(rt);}int query(int l,int r,int L,int R,int rt){ if(l==L&&r==R){ return sum[rt]%mod; } pushdown(L,R,rt); int mid=L+R>>1; if(r<=mid) return query(l,r,L,mid,rt<<1)%mod; else if(l>mid) return query(l,r,mid+1,R,rt<<1|1)%mod; else{query(mid+1,r,mid+1,R,rt<<1|1))%mod; }}int main(){ while(scanf("%lld%lld",&n,&mod)!=EOF){ build(1,n,1); scanf("%lld",&m); for(int i=1;i<=m;i++){ int k,l,r,c; scanf("%d%d%d",&k,&l,&r); if(k==3){ int ans=query(l,r,1,n,1); printf("%d\n",ans); }else{ scanf("%d",&c); if(k==1){ update(l,r,1,n,1,c,1); }else{ update(l,r,1,n,1,c,2); } } } } return 0;}
阅读全文
0 0
- 线段树?线段树!
- 线段树?线段树!
- 线段_线段树
- 线段_线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- 线段树
- count distinct基数统计之一
- Tomcat中找不到JSP编译后的java文件
- C++程序员学Java系列之三四:泛型
- Android插件DSL参考
- iOS系列开发-UITableView性能优化
- 线段树
- java private修饰的类和变量
- GCC for Windows 环境变量配置
- 利用放射性渐变实现css3渐变色边框
- OC语言学习21-分类应用
- Python数据分析-数据处理-数据导入
- Python数据分析-数据处理-数据导入与导出
- JS与面向对象
- 关于Linux里cp这个命令心得