hdu 4267 A Simple Problem with Integers 线段树维护不连续点
来源:互联网 发布:图片生成视频软件 编辑:程序博客网 时间:2024/06/06 11:40
题意:给出n个数两种操作, 1,查询第i个数是什么,2,输入a, b, k, c,然后所有满足在区间[a, b]里面的下标i 满足(i - a)% k == 0的全部加上c。
首先可以将每隔k的数看成一堆(如 x , x + k...),对于每堆都可以由线段树维护。那么,需要开多少颗线段树呢,可以这么看,k最大为10,那么 %k = (0, 1, 2, ....k-1 = 9)共有十堆,也可以当k = 1时,%k = 0(第一个),k = 2时,%k = 0, 1(第二,三个)一直到k = 10,%k = (0, 1, 2, 3...9),加起来一共55堆,这里采用的是后者。至于查询,只需要在k = 1~10时分别求和即可。那么怎么确定对那堆数进行维护呢?我们可以对每堆进行编号,从0 一直到54(因为是模嘛),只要确定是那一堆,就可以解决问题了
由 (i - a )% k== 0,转化为i % k == a % k,有a, k已知,则令j = a % k也已知,由于这里k ~ (1 ~ 10),所以开一个辅助数组t[11] [11],t [ i ] [ j ]表示i % k == a % k == j,即满足(i - a) % k == 0,那么就可以直接对编好号的线段树进行操作就可以了。
#include <map>#include <set>#include <queue>#include <stack>#include <vector>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1 | 1#define pi acos(-1.0)#define eps 1e-8#define asd puts("sdasdasdasdasd");typedef long long ll;const int inf = 0x3f3f3f3f;const int N = 50050;struct node{ int l, r, add[55], lazy, x;}tr[N << 2];int t[11][11]; // t[i][j]表示 i % k == a % k == j,即满足(i - a) % k == 0//k = 1时第一个元素为0, k = 2时, 第2,3个元素为0, 1....依次类推int n, q;void build( int l, int r, int rt ){ tr[rt].l = l; tr[rt].r = r; memset( tr[rt].add, 0, sizeof( tr[rt].add ) ); tr[rt].lazy = 0; if( l == r ) { scanf("%d", &tr[rt].x); return; } int mid = (l + r) >> 1; build( lson ); build( rson );}void down( int rt ){ if( tr[rt].lazy ) { tr[rt<<1].lazy += tr[rt].lazy; tr[rt<<1|1].lazy += tr[rt].lazy; tr[rt].lazy = 0; for( int i = 0; i < 55; i++ ) { tr[rt<<1].add[i] += tr[rt].add[i]; tr[rt<<1|1].add[i] += tr[rt].add[i]; tr[rt].add[i] = 0; } }}void update( int l, int r, int rt, int k, int mod, int x ){ if( l <= tr[rt].l && tr[rt].r <= r ) { tr[rt].lazy += x; tr[rt].add[ t[k][mod] ] += x; return; } down( rt ); int mid = ( tr[rt].l + tr[rt].r ) >> 1; if( l <= mid ) update( l, r, rt << 1, k, mod, x ); if( r > mid ) update( l, r, rt << 1 | 1, k, mod, x );}int query( int pos, int rt ){ if( tr[rt].l == tr[rt].r ) { int res = tr[rt].x; for( int i = 1; i <= 10; i++ ) res += tr[rt].add[ t[i][pos%i] ]; return res; } down( rt ); int mid = ( tr[rt].l + tr[rt].r ) >> 1; if( pos <= mid ) return query( pos, rt << 1 ); else return query( pos, rt << 1 | 1 );}int main(){ int cnt = 0; for( int i = 1; i <= 10; ++i ) { for( int j = 0; j < i; ++j ) t[i][j] = cnt++; } while( ~scanf("%d", &n) ) { build( 1, n, 1 ); scanf("%d", &q); int a, b, c, k, op; while( q-- ) { scanf("%d", &op); if( op == 1 ) { scanf("%d%d%d%d", &a, &b, &k, &c); update( a, b, 1, k, a % k, c ); } else { scanf("%d", &a); int ans = query( a, 1 ); printf("%d\n", ans); } } } return 0;}
0 0
- hdu 4267 A Simple Problem with Integers 线段树维护不连续点
- HDU 4267 A Simple Problem with Integers (55棵线段树更新维护)
- hdu 4267 A Simple Problem with Integers(线段树)
- HDU 4267 A Simple Problem with Integers (线段树)
- HDU 4267 A Simple Problem with Integers(线段树)
- HDU 4267 A Simple Problem with Integers (线段树)
- HDU 4267 A Simple Problem with Integers(线段树)
- 【hdu】A Simple Problem with Integers (线段树)
- A Simple Problem with Integers(线段树)
- A Simple Problem with Integers----线段树
- 线段树 A Simple Problem with Integers
- 线段树 A Simple Problem with Integers
- HDOJ 4267 A Simple Problem with Integers(线段树)
- hdoj 4267 A Simple Problem with Integers 【线段树】
- HDU 4267 - A Simple Problem with Integers
- hdu 4267 A Simple Problem with Integers
- hdu 4267 A Simple Problem with Integers
- hdu 4267 A Simple Problem with Integers
- c++函数名前面&的问题
- LeetCode: Longest Substring Without Repeating Characters
- Closest Sums - UVa10487 二分
- C++函数模板和类模板
- Android 自定义控件简单Demo
- hdu 4267 A Simple Problem with Integers 线段树维护不连续点
- 堆栈的区别
- C++指向类成员的指针的使用(详细介绍)
- C++ 类的静态成员详细讲解(一)
- C++ 类的静态成员详细讲解(二)
- 重载运算符
- char *a="hello";
- strcpy函数
- win32框架