bzoj 4373: 算术天才⑨与等差数列 hash
2016-02-25 23:25
357 查看
题目链接
题目大意: 给你n个数, 给两种操作, 一种给你l, r, k,问你[l, r]区间里的数排序后能否构成一个公差为k的等差数列。 另一种是将位置x的数变为y。 强制在线。
可以用hash来做, 用线段树保存一个区间里的最小值, 和, 以及平方的和。 然后每次询问, 假设这个区间构成等差数列,那么首项为这个区间的最小值, 然后按公式算出以minn为首项, k为公差的数列的和, 为a1*len+len*(len-1)/2*d, 然后算出平方的和, 相当于sigma(i : 0 to len-1) (a1+i*d)^2, 然后把它拆开, 就变成a1*a1*len+a1*d*len*(len-1)+d*d*len*(len-1)*(2*len-1)/6, 记得时刻取模防止爆longlong, /6那里用乘法逆元算。 然后看是否相等就可以了。
正解当然不是这样的..
题目大意: 给你n个数, 给两种操作, 一种给你l, r, k,问你[l, r]区间里的数排序后能否构成一个公差为k的等差数列。 另一种是将位置x的数变为y。 强制在线。
可以用hash来做, 用线段树保存一个区间里的最小值, 和, 以及平方的和。 然后每次询问, 假设这个区间构成等差数列,那么首项为这个区间的最小值, 然后按公式算出以minn为首项, k为公差的数列的和, 为a1*len+len*(len-1)/2*d, 然后算出平方的和, 相当于sigma(i : 0 to len-1) (a1+i*d)^2, 然后把它拆开, 就变成a1*a1*len+a1*d*len*(len-1)+d*d*len*(len-1)*(2*len-1)/6, 记得时刻取模防止爆longlong, /6那里用乘法逆元算。 然后看是否相等就可以了。
正解当然不是这样的..
#include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set> #include <string> #include <queue> #include <stack> #include <bitset> using namespace std; #define pb(x) push_back(x) #define ll long long #define mk(x, y) make_pair(x, y) #define lson l, m, rt<<1 #define mem(a) memset(a, 0, sizeof(a)) #define rson m+1, r, rt<<1|1 #define mem1(a) memset(a, -1, sizeof(a)) #define mem2(a) memset(a, 0x3f, sizeof(a)) #define rep(i, n, a) for(int i = a; i<n; i++) #define fi first #define se second typedef pair<int, int> pll; const double PI = acos(-1.0); const double eps = 1e-8; const ll mod = 1e9+7; const ll inf = 1e18; const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; const int maxn = 3e5+5; ll sum1[maxn<<2], sum2[maxn<<2], minn[maxn<<2], ans1, ans2, ans3; void pushUp(int rt) { sum1[rt] = sum1[rt<<1]+sum1[rt<<1|1]; sum2[rt] = (sum2[rt<<1] + sum2[rt<<1|1])%mod; minn[rt] = min(minn[rt<<1], minn[rt<<1|1]); } void build(int l, int r, int rt) { if(l == r) { scanf("%I64d", &sum1[rt]); minn[rt] = sum1[rt]; sum2[rt] = sum1[rt]*sum1[rt]%mod; return ; } int m = l+r>>1; build(lson); build(rson); pushUp(rt); } void update(int p, ll val, int l, int r, int rt) { if(l == r) { sum1[rt] = minn[rt] = val; sum2[rt] = val*val%mod; return ; } int m = l+r>>1; if(p<=m) update(p, val, lson); else update(p, val, rson); pushUp(rt); } void query(int L, int R, int l, int r, int rt) { if(L<=l&&R>=r) { ans1 += sum1[rt]; ans2 = (ans2+sum2[rt])%mod; ans3 = min(ans3, minn[rt]); return ; } int m = l+r>>1; if(L<=m) query(L, R, lson); if(R>m) query(L, R, rson); } ll pow(ll a, ll b) { ll ret = 1; while(b) { if(b&1) { ret = ret*a%mod; } a = a*a%mod; b>>=1; } return ret; } ll get1(ll a1, ll l, ll d) { ll ret = a1*l+l*(l-1)/2*d; return ret; } ll get2(ll a1, ll l, ll d) { ll ret = a1*a1%mod*l%mod; ll rev = pow(6LL, mod-2)%mod; ret = (ret + d*d%mod*l%mod*(l-1)%mod*(2*l-1)%mod*rev%mod)%mod; ret = (ret + a1*d%mod*l%mod*(l-1)%mod)%mod; return ret%mod; } int main() { int n, m, cnt = 0, sign, x, y, z; cin>>n>>m; build(1, n, 1); while(m--) { scanf("%d%d%d", &sign, &x, &y); x ^= cnt, y ^= cnt; if(sign == 1) { update(x, 1LL*y, 1, n, 1); } else { scanf("%d", &z); z ^= cnt; ans3 = inf, ans1 = ans2 = 0; query(x, y, 1, n, 1); ll tmp1 = get1(ans3, y-x+1, z); ll tmp2 = get2(ans3, y-x+1, z); if(tmp1 == ans1 && tmp2 == ans2) { cnt++; puts("Yes"); } else { puts("No"); } } } return 0; }
相关文章推荐
- 贪心算法知识点补充
- PHP程序的原子性和PHP的文件锁
- 2016年学习计划
- OS模块
- UVA 815(p99)----Flooded!
- JAVA中获取当前系统时间
- Hexo搭建Github静态博客(windows)
- 学长的训诫C++
- UVA 808(p342)----Bee Breeding
- 一个七年程序员的经验
- LInux内核分析——计算机是如何工作的进行
- leetcode-115-Triangle
- POJ 3177 Redundant Paths(Tarjan_BCC+缩点)
- 加载内核模块,实现新的系统调用:遍历系统当前所有进程的任务描述符,并将pid组织成树状结构显示
- UVA 725(p182)----Division
- 欢迎使用CSDN-markdown编辑器
- mysql中的trigger
- chart控件的简单使用
- C语言的整型和长整型的字节长
- 大龄恐惧症 (zz)