您的位置:首页 > 其它

BZOJ 2743: [HEOI2012]采花

2016-12-20 17:31 477 查看

2743: [HEOI2012]采花

Time Limit: 15 Sec Memory Limit: 128 MB
Submit: 2056 Solved: 1059
[Submit][Status][Discuss]

Description

[align=left]萧芸斓是Z国的公主,平时的一大爱好是采花。[/align]
今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花。花园足够大,容纳了n朵花,花有c种颜色(用整数1-c表示),且花是排成一排的,以便于公主采花。公主每次采花后会统计采到的花的颜色数,颜色数越多她会越高兴!同时,她有一癖好,她不允许最后自己采到的花中,某一颜色的花只有一朵。为此,公主每采一朵花,要么此前已采到此颜色的花,要么有相当正确的直觉告诉她,她必能再次采到此颜色的花。由于时间关系,公主只能走过花园连续的一段进行采花,便让女仆福涵洁安排行程。福涵洁综合各种因素拟定了m个行程,然后一一向你询问公主能采到多少朵花(她知道你是编程高手,定能快速给出答案!),最后会选择令公主最高兴的行程(为了拿到更多奖金!)。

Input

[align=left] 第一行四个空格隔开的整数n、c以及m。接下来一行n个空格隔开的整数,每个数在[1, c]间,第i个数表示第i朵花的颜色。接下来m行每行两个空格隔开的整数l和r(l ≤ r),表示女仆安排的行程为公主经过第l到第r朵花进行采花。[/align]

Output

[align=left] [/align]
[align=left]共m行,每行一个整数,第i个数表示公主在女仆的第i个行程中能采到的花的颜色数。[/align]

Sample Input

5 3 5

1 2 2 3 1

1 5

1 2

2 2

2 3

3 5

Sample Output

2

0 0 1 0

【样例说明】

询问[1, 5]:公主采颜色为1和2的花,由于颜色3的花只有一朵,公主不采;询问[1, 2]:颜色1和颜色2的花均只有一朵,公主不采;

询问[2, 2]:颜色2的花只有一朵,公主不采;

询问[2, 3]:由于颜色2的花有两朵,公主采颜色2的花;

询问[3, 5]:颜色1、2、3的花各一朵,公主不采。

HINT

【数据范围】

对于100%的数据,1 ≤ n ≤ 10^6,c ≤ n,m ≤10^6。

Source

[Submit][Status][Discuss]

用莫队据说会TLE,有人实践了一下,@NEIGHTHORN

那就只好离线+树状数组喽,预处理每种颜色的下一个出现位置,从左向右枚举左端点即可。

#include <bits/stdc++.h>

#define siz 1024

inline int get_c(void)
{
static char buf[siz];
static char *head = buf + siz;
static char *tail = buf + siz;

if (head == tail)
fread(head = buf, 1, siz, stdin);

return *head++;
}

inline int get_i(void)
{
register int ret = 0;
register int neg = false;
register int bit = get_c();

for (; bit < 48; bit = get_c())
if (bit == '-')neg ^= true;

for (; bit > 47; bit = get_c())
ret = ret * 10 + bit - 48;

return neg ? -ret : ret;
}

#define N 1000005

int n;
int c;
int m;
int lt
;
int rt
;
int ans
;
int ord
;
int num
;
int nxt
;
int lst
;
int fst
;
int tree
;

inline bool cmp(int a, int b)
{
return lt[a] < lt[b];
}

inline int ask(int p)
{
int ret = 0;
for (; p; p -= p&-p)
ret += tree[p];
return ret;
}

inline void add(int p, int k)
{
for (; p <= n; p += p&-p)
tree[p] += k;
}

signed main(void)
{
n = get_i();
c = get_i();
m = get_i();

for (int i = 1; i <= n; ++i)
num[i] = get_i();

for (int i = 1; i <= m; ++i)
{
ord[i] = i;
lt[i] = get_i();
rt[i] = get_i();
}

std::sort(ord + 1, ord + 1 + m, cmp);

nxt[n + 1] = n + 1;

for (int i = 1; i <= c; ++i)
lst[i] = n + 1, fst[i] = 0;

for (int i = n; i >= 1; --i)
nxt[i] = lst[num[i]], lst[num[i]] = i;

for (int i = 1; i <= n; ++i)
if (!fst[num[i]])
{
add(nxt[i], 1);
fst[num[i]] = 1;
}

int left = 1;

for (int i = 1; i <= m; ++i)
{
while (left < lt[ord[i]])
{
add(nxt[left], -1);
add(nxt[nxt[left]], 1);
++left;
}

ans[ord[i]] = ask(rt[ord[i]]);
}

for (int i = 1; i <= m; ++i)
printf("%d\n", ans[i]);
}


#include <bits/stdc++.h>

const int mxn = 1000005;

int n, m, col[mxn];

namespace BIT
{
int tree[mxn];

void add(int p, int v)
{
for (; p <= n; p += p&-p)
tree[p] += v;
}

int qry(int p)
{
int ret = 0;

for (; p >= 1; p -= p&-p)
ret += tree[p];

return ret;
}
}

namespace PRW
{
int nxt[mxn];
int lst[mxn];

void prework(void)
{
nxt[n + 1] = n + 1;

for (int i = 1; i <= n + 1; ++i)
lst[i] = n + 1;

for (int i = n; i >= 1; --i)
{
nxt[i] = lst[col[i]];
lst[col[i]] = i;
}

for (int i = 1; i <= n; ++i)
BIT::add(nxt[lst[i]], 1);
}
}

namespace QRY
{
struct query
{
int l, r, ans;
}qry[mxn];

int hd[mxn], to[mxn], nt[mxn], tot;

void add(int u, int v)
{
nt[++tot] = hd[u], to[tot] = v, hd[u] = tot;
}

void read(int i)
{
scanf("%d%d", &qry[i].l, &qry[i].r);

add(qry[i].l, i);
}
}

signed main(void)
{
scanf("%d%*d%d", &n, &m);

for (int i = 1; i <= n; ++i)
scanf("%d", col + i);

PRW::prework();

for (int i = 1; i <= m; ++i)
QRY::read(i);

for (int i = 1; i <= n; ++i)
{
for (int j = QRY::hd[i]; j; j = QRY::nt[j])
{
int q = QRY::to[j];

QRY::qry[q].ans = BIT::qry(QRY::qry[q].r);
}

BIT::add(PRW::nxt[i], -1);
BIT::add(PRW::nxt[PRW::nxt[i]], 1);
}

for (int i = 1; i <= m; ++i)
printf("%d\n", QRY::qry[i].ans);
}


View Code

@Author: YouSiki
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: