Educational Codeforces Round 22 E. Army Creation 主席树 或 分块
http://codeforces.com/contest/813/problem/E
题目大意:
给出长度为n的数组和k, 大小是1e5级别。
要求在线询问区间[l, r]权值, 权值定义为对于所有不同元素x在区间出现的次数和, 如果x出现次数>k, 那么按k算。
重要转换: 考虑一个区间[L, R]的某个数A[i], 它对答案有贡献 当且仅当 它前面与他权值相同的数中第k个数的位置(记为B[i]) < L
预处理B[], 每次询问就转化为 区间[L, R]中有多少个B[i] < L
可以用主席树 或者 分块解决。
也可以用此题的方法求区间不同元素个数, 其实就是k = 1的情况。
主席树代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
using namespace std; typedef long long ll; #define N 100050
const int INF = << ;
const double pi = acos(-); int pt;
int a[N], b[N], root[N], lc[N * ], rc[N * ], cnt[N * ];
vector<int> lis[N]; int Add(int y, int l, int r, int v)
{
int x = ++pt;
cnt[x] = cnt[y] + ;
if (l < r)
{
int mid = (l + r) >> ;
if (v <= mid)
{
rc[x] = rc[y];
lc[x] = Add(lc[y], l, mid, v);
}
else
{
lc[x] = lc[y];
rc[x] = Add(rc[y], mid + , r, v);
}
}
return x;
} int Query(int x, int y, int L, int R, int l, int r)
{
//cout << L <<" " << R << " " << cnt[x] << " " << cnt[y] << endl;
if (l > R || r < L) return ;
if (l <= L && r >= R) return cnt[x] - cnt[y]; int Mid = (L + R) >> ;
return Query(lc[x], lc[y], L, Mid, l, r) + Query(rc[x], rc[y], Mid + , R, l, r);
} int main()
{
//freopen("in.in", "r", stdin);
//freopen("out.out", "w", stdout); int n, k, Q, lastans = , l, r;
scanf("%d %d", &n, &k);
for (int i = ; i <= n; ++i) scanf("%d", &a[i]), lis[a[i]].push_back(i); for (int i = ; i <= ; ++i)
{
if (lis[i].size() <= k) continue;
for (int j = k; j < lis[i].size(); ++j) b[lis[i][j]] = lis[i][j - k];
} root[] = ++pt;
for (int i = ; i <= n; ++i) root[i] = Add(root[i - ], , n, b[i]); scanf("%d", &Q);
while (Q--)
{
scanf("%d %d", &l, &r);
l = (l + lastans) % n + ;
r = (r + lastans) % n + ;
if (l > r) swap(l, r);
lastans = Query(root[r], root[l - ], , n, , l - );
printf("%d\n", lastans);
} return ;
}
分块代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
using namespace std; typedef long long ll; #define N 100050
const int INF = << ;
const double pi = acos(-); int pt;
int a[N], b[N], id[N], dp[][N];
int bl[], br[];
vector<int> lis[N]; int main()
{
//freopen("in.in", "r", stdin);
//freopen("out.out", "w", stdout); int n, k, Q, lastans = , l, r;
scanf("%d %d", &n, &k);
for (int i = ; i <= n; ++i) scanf("%d", &a[i]), lis[a[i]].push_back(i); for (int i = ; i <= ; ++i)
{
if (lis[i].size() <= k) continue;
for (int j = k; j < lis[i].size(); ++j) b[lis[i][j]] = lis[i][j - k];
} int block = (int)sqrt(n + ); for (int i = ; ; ++i)
{
l = (i - ) * block + ;
r = min(n, l + block - );
bl[i] = l, br[i] = r;
for (int j = l; j <= r; ++j) dp[i][b[j]]++, id[j] = i;
for (int j = ; j <= ; ++j) dp[i][j] += dp[i][j - ];
if (r == n) break;
} scanf("%d", &Q);
while (Q--)
{
scanf("%d %d", &l, &r);
l = (l + lastans) % n + ;
r = (r + lastans) % n + ;
if (l > r) swap(l, r); int res = ;
if (id[l] == id[r])
{
for (int i = l; i <= r; ++i)
res += b[i] < l;
}
else
{
for (int i = l; i <= br[id[l]]; ++i) res += b[i] < l;
for (int i = bl[id[r]]; i <= r; ++i) res += b[i] < l;
for (int i = id[l] + ; i <= id[r] - ; ++i) res += dp[i][l - ];
}
printf("%d\n", res);
lastans = res;
} return ;
}
Educational Codeforces Round 22 E. Army Creation 主席树 或 分块的更多相关文章
- Educational Codeforces Round 22 E. Army Creation
Educational Codeforces Round 22 E. Army Creation 题意:求区间[L,R]内数字次数不超过k次的这些数字的数量的和 思路:和求区间内不同数字的数量类似,由 ...
- Educational Codeforces Round 22 E. Army Creation(分块好题)
E. Army Creation time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...
- [Educational Codeforces Round#22]
来自FallDream的博客,未经允许,请勿转载,谢谢. 晚上去clj博客逛来逛去很开心,突然同学提醒了一下,发现cf已经开始40分钟了,慌的一B,从B题开始写,写完了B到E最后收掉了A,结果太着急B ...
- Educational Codeforces Round 22 补题 CF 813 A-F
A The Contest 直接粗暴贪心 略过 #include<bits/stdc++.h> using namespace std; int main() {//freopen(&qu ...
- Educational Codeforces Round 22.B 暴力
B. The Golden Age time limit per test 1 second memory limit per test 256 megabytes input standard in ...
- Educational Codeforces Round 22 B. The Golden Age(暴力)
题目链接:http://codeforces.com/contest/813/problem/B 题意:就是有一个数叫做不幸运数,满足题目的 n = x^a + y^b,现在给你一个区间[l,r],让 ...
- 【Educational Codeforces Round 22】
又打了一场EDU,感觉这场比23难多了啊…… 艹还是我太弱了. A. 随便贪心一下. #include<bits/stdc++.h> using namespace std; ,ans=- ...
- CF Educational Codeforces Round 10 D. Nested Segments 离散化+树状数组
题目链接:http://codeforces.com/problemset/problem/652/D 大意:给若干个线段,保证线段端点不重合,问每个线段内部包含了多少个线段. 方法是对所有线段的端点 ...
- Educational Codeforces Round 12 E. Beautiful Subarrays 字典树
E. Beautiful Subarrays 题目连接: http://www.codeforces.com/contest/665/problem/E Description One day, ZS ...
随机推荐
- java中Runtime类
一.概述 Runtime类封装了运行时的环境.每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接. 一般不能实例化一个Runtime对象, ...
- 用Markdown写博客快速入门
Markdown,简单来说,就是一种可以方便转换为HTML的带标记符号纯文本. 它是对我等键盘党的福音:我不用再费劲挪动鼠标去按加粗.设置段落了,用键盘输入所有文本,一气呵成. 最重要的是,cnblo ...
- 求字符串A与字符串B的最长公共字符串(JAVA)
思路:引入一个矩阵的思想,把字符串A(长度为m)当成矩阵的行,把字符串B(长度为n)当矩阵的列.这样就构成一个m*n的矩阵.若该矩阵的节点相应的字符同样,即m[i]=n[j]时.该节点值为1:当前字符 ...
- 【VBA编程】07.循环结构语句
[FOR...NEXT语句] For counter = start To End [Step step] [statements] [Exit For] [statements] Next [cou ...
- Mac系统使用命令行快捷打开Sublime
本篇文章由:http://xinpure.com/use-command-line-shortcuts-to-open-the-mac-system-sublime/ 方法一 使用软链接 ln -s ...
- Android之常用功能代码
透明导航栏 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { getWindow().addFlags(WindowManage ...
- linux系统常用命令 -设置文件夹读写权限
设置文件夹的读写权限: sudo chmod -R 777 /data 权限码描述 sudo chmod 600 ××× (只有所有者有读和写的权限)sudo chmod 644 ××× (所有者有读 ...
- 折腾docker安装笔记
最近尝试把netcore迁移到docker,然后在本地虚拟机尝试装下 发现yum安装好复杂 于是记录下 1.7.2 centos的ios装虚拟机 2.修改网络 配置文件 查看网络地址 然后xshell ...
- Android USB转串口通信开发基本流程
好久没有写文章了,年前公司新开了一个项目,是和usb转串口通信相关的,需求是用安卓平板通过usb转接后与好几个外设进行通信.一直忙到近期,才慢慢闲下来,趁着这个周末不忙.记录下usb转串口通信开发的基 ...
- mysql-group-replication 测试环境的搭建与排错
mysql-group-replication 是由mysql-5.7.17这个版本提供的强一致的高可用集群解决方案 1.环境规划 主机ip 主机名 172.16.192.201 balm001 17 ...