【可持久化线段树】[COCI]白雪公主(white)
题目描述:
白雪公主和N个小矮人住在森林里。每天早上,矮人们排成一队出去挖矿的路上,白雪公主就负责给他们拍照,并把这些照片传到社交网络上去。
白雪每次都会拍很多照片,她要从中选出一些完美的照片。小矮人们都戴着不同颜色的
帽子。如果照片上小矮人们有一半以上人戴着相同颜色的帽子,则这张照片就算是完美的。
也就是说,如果照片上有K个人,如果有多于K/2的人带着相同颜色的帽子,则这张照片就是完美的。
现在,写一个程序来检测相片集M是不是完美的,并且判断出完美照片上,哪种是主要的颜色。
输入:
第一行包含2个整数N和C(3≤N≤300000,1≤C≤10000),矮人的数目和帽子颜色的种类。
第二行包含N个1到C的整数,表示帽子的颜色,按照矮人们走路的先后顺序给出。
第三行包含M(1≤M≤10000),表示照片的数目。
接下来M行包含2个整数A,B(1≤A≤B≤N)。每一行描述了一张照片,照片上有第A个人到第B个人。
输出:
M行,如果那张照片不完美,则输出“no”,否则输出“yes X”,X表示照片上主要的颜色。
30%的数据,M小于10.
30%的数据,C小于10.
样例输入:
10 3
1 2 1 2 1 2 3 2 3 3
8
1 2
1 3
1 4
1 5
2 5
2 6
6 9
7 10
样例输出:
no
yes 1
no
yes 1
no
yes 2
no
yes 3
首先用可持久化线段树统计到
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long LL;
const LL MAXT = 4500000;
const LL MAXN = 300000;
struct Node{
LL lch, rch;
LL sum;
Node(){sum = lch = rch = 0;}
}Tree[MAXT+10];
LL rts[MAXN+10], ttot;
inline LL mid(LL l, LL r){return l + ((r - l) >> 1);}
void Insert(LL &now, LL val, LL l, LL r){
if(val < l || val > r) return ;
Tree[++ttot] = Tree[now];
now = ttot;
Tree[now].sum++;
if(l == r) return ;
if(val <= mid(l, r)) Insert(Tree[now].lch, val, l, mid(l,r));
else Insert(Tree[now].rch, val, mid(l,r)+1, r);
}
int ans;
bool Query(LL now, LL up, LL L, LL R, LL least){
if(L == R){
ans = L;
return true;
}
int _mid = mid(L, R);
if(Tree[Tree[now].lch].sum - Tree[Tree[up].lch].sum > least)
if(Query(Tree[now].lch, Tree[up].lch, L, _mid, least))
return true;
if(Tree[Tree[now].rch].sum - Tree[Tree[up].rch].sum > least)
if(Query(Tree[now].rch, Tree[up].rch, _mid+1, R, least))
return true;
ans = -1;
return false;
}
int main(){
int n, C, tmp, A, B;
scanf("%d%d", &n, &C);
for(int i=1;i<=n;i++){
scanf("%d", &tmp);
rts[i] = rts[i-1];
Insert(rts[i], tmp, 1, C);
}
int m;
scanf("%d", &m);
for(int i=1;i<=m;i++){
scanf("%d%d", &A, &B);
Query(rts[B], rts[A-1], 1, C, (B-A+1)/2);
if(ans == -1) printf("no\n");
else printf("yes %d\n", ans);
}
return 0;
}