看了几天学会了模板的写法
主席树主要是用来求区间第k大的 划分树也可以解决 但是划分树只能静态 如果要动态(带修改点) 就可以结合树状数组
还有一类树上主席树 like求两个点之间的第k大点权 就可以用在线lca求出lca来 然后用 x y lca fa[lca] 来做一下加减 求第k大
虽然知道解法但是只写了几道普通的求k大题 数据结构写起来想睡觉 ...
HDU 5919
从后往前建树 每次都在这颗树中减去上次a[i]出现的index 加上这次的index 这样就保证了 当前的root[i] 里面存的index没有相同的数字 只会保存该数字最左的
如果要求lr的中位数 这时候不用相减 只需要求root[l]这颗线段树中的[l,r]区间的第k大就可以了
Online Judge Online Exercise Online Teaching Online Contests Exercise Author
F.A.Q
Hand In Hand
Online Acmers
Forum | Discuss
Statistical Charts
Problem Archive
Realtime Judge Status
Authors Ranklist
C/C++/Java Exams
ACM Steps
Go to Job
Contest LiveCast
ICPC@China
Best Coder beta
VIP | STD Contests
Virtual Contests
DIY | Web-DIY beta
Recent Contests
Author 1504010705
Mail Mail 0(0)
Control Panel Control Panel
Sign Out Sign Out
点击查看详情——《IJCAI 2017 口碑商家客流量预测大赛》
View Code
Problem : 5919 ( Sequence II ) Judge Status : Accepted
RunId : 19705448 Language : G++ Author : 1504010705
Code Render Status : Rendered By HDOJ G++ Code Render Version 0.01 Beta
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define L long long
const int maxn = 200050 ;
int root[maxn] ;
struct node {
int l , r , sum ;
}T[maxn * 40];
int cnt ;
int n , m ;
int a[maxn];
void build(int l, int r){
T[++cnt].sum = 0 ;
T[cnt].l = T[cnt].r = 0;
if(l == r) return ;
int mid = (l + r) / 2 ;
int x = cnt ;
T[x].l = cnt + 1;
build(l, mid) ;
T[x].r = cnt + 1;
build(mid+1,r) ;
}
int sc[maxn * 2] ;
void upda(int l , int r , int &x , int y , int i , int j ) {
T[++cnt] = T[y] ;
x = cnt ;
if(i >= l && i <= r)
T[cnt].sum ++;
if(j != -1 && j >= l && j <= r) T[cnt].sum -- ;
if(l == r)return ;
int mid = (l + r) / 2 ;
if((i >= l && i <= mid) || (j != -1 && j >= l && j <= mid)) {
upda(l,mid,T[x].l , T[y].l , i , j ) ;
}
if((i >= mid+1 && i <= r) || (j != -1 && j >= mid+1 && j <= r)) {
upda(mid+1,r,T[x].r , T[y].r , i , j ) ;
}
}
int ans[maxn] ;
int query(int l,int r,int ro,int ll , int rr) {
if(l <= ll && r >= rr) {
return T[ro].sum ;
}
int mid = ( ll + rr ) / 2 ;
if(r <= mid) {
return query(l,r,T[ro].l , ll,mid) ;
}
else if(l >= mid + 1) {
return query(l,r,T[ro].r , mid+1, rr) ;
}
else {
return query(l,r,T[ro].l,ll,mid) + query(l,r,T[ro].r,mid+1,rr) ;
}
}
int main(){
int t;
scanf("%d",&t);
int cas = 1 ;
while(t-- ){
scanf("%d%d",&n,&m) ;
for(int i = 1; i <= n ;i ++ ){
scanf("%d",&a[i]);
}
root[n+1] = 1;
cnt = 0 ;
build(1,n);
memset(sc , -1 , sizeof(sc)) ;
for(int i = n ; i >= 1 ; i -- ){
int x = a[i] ;
int j = sc[a[i]] ;
upda(1,n,root[i] ,root[i+1], i , j ) ;
sc[a[i]] = i ;
}
ans[0] = 0 ;
for(int i = 1; i <= m ; i ++ ) {
int ll, rr ;
scanf("%d%d",&ll,&rr);
int l = min((ll + ans[i-1])%n+1 ,(rr + ans[i-1])%n+1) ;
int r = max((ll + ans[i-1])%n+1 ,(rr + ans[i-1])%n+1) ;
int sum = query(l,r,root[l],1,n) ;
int k = sum / 2;
if(sum %2 != 0) k ++ ;
int ro = l ;
while(l <= r) {
if(l == r) {
ans[i] = l ;
break ;
}
int mid = (l + r) / 2 ;
int z = query(l,mid,root[ro],1,n) ;
if(z >= k ) {
r = mid ;
}
else {
l = mid + 1 ;
k -= z ;
}
}
}
printf("Case #%d: ",cas++ ) ;
for(int i = 1 ; i <= m ; i ++ ){
printf("%d",ans[i]);
if(i == m)printf("\n");
else printf(" ") ;
}
}
}
学习数据结构真是一件需要码力的事情 ..
原文:http://www.cnblogs.com/rayrayrainrain/p/6368282.html