博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2019 Multi-University Training Contest 10 - Make Rounddog Happy
阅读量:4951 次
发布时间:2019-06-11

本文共 2711 字,大约阅读时间需要 9 分钟。

分治 + ST表

先预处理出区间内最大值的位置和每个数向左和向右能够延伸的最大距离。

然后把每个区间的最大值的位置当成中点来分治统计每个数的贡献。

统计的时候选区间较短的统计,类似于启发式合并?

#include 
#define INF 0x3f3f3f3f#define full(a, b) memset(a, b, sizeof a)#define __fastIn ios::sync_with_stdio(false), cin.tie(0)#define pb push_backusing namespace std;using LL = long long;inline int lowbit(int x){ return x & (-x); }inline int read(){ int ret = 0, w = 0; char ch = 0; while(!isdigit(ch)){ w |= ch == '-', ch = getchar(); } while(isdigit(ch)){ ret = (ret << 3) + (ret << 1) + (ch ^ 48); ch = getchar(); } return w ? -ret : ret;}template
inline A __lcm(A a, A b){ return a / __gcd(a, b) * b; }template
inline A fpow(A x, B p, C lyd){ A ans = 1; for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd; return ans;}const int N = 300005;int _, n, k, a[N], L[N], R[N], pos[N], lb[N], st[N][25];LL ans;void initST(){ for(int i = 1; i <= n; i ++) st[i][0] = i; for(int j = 1; j <= 20; j ++){ for(int i = 1; i + (1 << j) - 1 <= n; i ++){ int p = st[i][j - 1], q = st[i + (1 << (j - 1))][j - 1]; st[i][j] = a[p] > a[q] ? p : q; } }}int query(int l, int r){ int t = lb[r - l + 1]; int p = st[l][t], q = st[r - (1 << t) + 1][t]; return a[p] > a[q] ? p : q;}void solve(int l, int r){ if(l > r) return; int mid = query(l, r); solve(l, mid - 1), solve(mid + 1, r); int x = a[mid] - k; if(mid - l < r - mid){ for(int i = l; i <= mid; i ++){ int lower = max(i + x - 1, mid); int upper = min(R[i], r); if(upper >= lower) ans += upper - lower + 1; } } else{ for(int i = mid; i <= r; i ++){ int lower = min(i - x + 1, mid); int upper = max(L[i], l); if(upper <= lower) ans += lower - upper + 1; } }}int main(){ lb[0] = -1; for(int i = 1; i < N; i ++) lb[i] = lb[i >> 1] + 1; for(_ = read(); _; _ --){ ans = 0; n = read(), k = read(); for(int i = 1; i <= n; i ++) a[i] = read(); for(int i = 1; i <= n; i ++) pos[i] = 0; for(int i = 1; i <= n; i ++){ L[i] = pos[a[i]] + 1; pos[a[i]] = i; } for(int i = 2; i <= n; i ++){ L[i] = max(L[i - 1], L[i]); } for(int i = 1; i <= n; i ++) pos[i] = n + 1; for(int i = n; i >= 1; i --){ R[i] = pos[a[i]] - 1; pos[a[i]] = i; } for(int i = n - 1; i >= 1; i --){ R[i] = min(R[i + 1], R[i]); } initST(); solve(1, n); printf("%lld\n", ans); } return 0;}

转载于:https://www.cnblogs.com/onionQAQ/p/11396759.html

你可能感兴趣的文章
NSSetUncaughtExceptionHandler
查看>>
bc#34-2 Building Blocks
查看>>
struts2自定义结果类型demo
查看>>
30个高质量的Psd设计文件分享
查看>>
生成器
查看>>
go 格式化时间戳
查看>>
Spring 2017 Assignments2
查看>>
查找进程并杀掉
查看>>
BZOJ 3943 [Usaco2015 Feb]SuperBull:最大生成树
查看>>
ueditor 控制上传图片的显示尺寸
查看>>
poj 1920 Towers of Hanoi
查看>>
第二十三模板 13模板成员
查看>>
oracle为IN OUT变量或OUT变量赋值时提示“表达式''不能用作赋值目标”
查看>>
AWS AppSync 的基本语句
查看>>
Ubuntu 使用unzip解压乱码的问题
查看>>
[转发]iptables中DNAT与SNAT的理解
查看>>
ListView显示不同行以及数据重用
查看>>
12-五子棋游戏:享元模式
查看>>
css3系列之详解border-radius
查看>>
团队—科学计算器——项目进度
查看>>