HDU 5919 - Sequence II (2016CCPC长春) 主席树 (区间第K小+区间不同值个数)

HDU 5919

题意:

  动态处理一个序列的区间问题,对于一个给定序列,每次输入区间的左端点和右端点,输出这个区间中:每个数字第一次出现的位子留下, 输出这些位子中最中间的那个,就是(len+1)/2那个。

思路:

  主席树操作,这里的思路是从n到1开始建树。其他就是主席树查询区间第K小,计算区间不同值个数。

#include <algorithm>
#include  <iterator>
#include  <iostream>
#include   <cstring>
#include   <cstdlib>
#include   <iomanip>
#include    <bitset>
#include    <cctype>
#include    <cstdio>
#include    <string>
#include    <vector>
#include     <stack>
#include     <cmath>
#include     <queue>
#include      <list>
#include       <map>
#include       <set>
#include   <cassert>
#include <unordered_map>
using namespace std;
//#pragma GCC optimize(3)
//#pragma comment(linker, "/STACK:102400000,102400000")  //c++
// #pragma GCC diagnostic error "-std=c++11"
// #pragma comment(linker, "/stack:200000000")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#define lson (l , mid , rt << 1)
#define rson (mid + 1 , r , rt << 1 | 1)
#define debug(x) cerr << #x << " = " << x << "\n";
#define pb push_back
#define pq priority_queue
#define max3(a,b,c) max(max(a,b),c)

typedef long long ll;
typedef unsigned long long ull;

typedef pair<ll ,ll > pll;
typedef pair<int ,int > pii;
typedef pair<int,pii> p3;

//priority_queue<int> q;//这是一个大根堆q
//priority_queue<int,vector<int>,greater<int> >q;//这是一个小根堆q
#define fi first
#define se second
//#define endl ‘\n‘

#define OKC ios::sync_with_stdio(false);cin.tie(0)
#define FT(A,B,C) for(int A=B;A <= C;++A)  //用来压行
#define REP(i , j , k)  for(int i = j ; i <  k ; ++i)
//priority_queue<int ,vector<int>, greater<int> >que;

const ll mos = 0x7FFFFFFF;  //2147483647
const ll nmos = 0x80000000;  //-2147483648
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3f; //18
const int mod = 256;
const double esp = 1e-8;
const double PI=acos(-1.0);

template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<‘0‘||ch>‘9‘) f|=(ch==‘-‘),ch=getchar();
    while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
    return x=f?-x:x;
}

/*-----------------------showtime----------------------*/
            const int maxn = 2e5+9;
            struct node {
                int l,r;
                int sum;
            } t[maxn*40];
            int tot;
            int vis[maxn],rt[maxn],a[maxn];

            void update(int l,int r,int &x, int y,int pos,int val){
                tot++; x = tot;
                t[x] = t[y];
                t[x].sum += val;
                if(l == r)return;
                int mid = (l + r) >> 1;
                if(pos <= mid) update(l,mid,t[x].l,t[y].l,pos,val);
                else update(mid+1,r,t[x].r,t[y].r,pos,val);
            }

            int query(int l,int r,int x,int L, int R){
                if(l >= L && r<=R){
                    return t[x].sum;
                }
                int mid = (l + r) >> 1;
                int res = 0;
                if(mid >= L) res += query(l,mid,t[x].l,L,R);
                if(mid <  R) res += query(mid+1,r,t[x].r,L,R);
                return res;
            }

            int getk(int l,int r,int x,int k){
                if(l == r)return l;
                int cnt = t[t[x].l].sum;
                int mid = (l+r)>>1;
                if(cnt >= k) return getk(l,mid,t[x].l,k);
                else return getk(mid+1, r,t[x].r,k-cnt);
            }
int main(){
            int T,n,m;  scanf("%d", &T);
            for(int tt=1; tt<=T; tt++){
                tot = 0;
                scanf("%d%d", &n, &m);
                for(int i=1; i<=n; i++)scanf("%d", &a[i]);
                memset(vis, -1, sizeof(vis));
                memset(rt, 0, sizeof(rt));
                for(int i=n; i>=1; i--){
                    if(vis[a[i]] == -1){
                        update(1,n,rt[i],rt[i+1],i,1);
                    }
                    else{
                        int tmp;
                        update(1,n,tmp,rt[i+1], vis[a[i]], -1);
                        update(1,n,rt[i],tmp,i,1);
                    }
                    vis[a[i]] = i;
                }
                printf("Case #%d:", tt);
                int la = 0;
                for(int i=1; i<=m; i++){
                    int l,r,L,R;    scanf("%d%d", &L, &R);
                    l = min((L+la)%n + 1, (R+la)%n + 1);
                    r = max((L+la)%n + 1, (R+la)%n + 1);
                    int k = query(1,n,rt[l],l,r);
                    k = (k + 1) / 2;
                    la = getk(1,n,rt[l],k);
                    printf(" %d", la);
                }
                puts("");
            }
            return 0;
}

HDU - 5919

  

原文地址:https://www.cnblogs.com/ckxkexing/p/9966890.html

时间: 2024-12-19 23:14:18

HDU 5919 - Sequence II (2016CCPC长春) 主席树 (区间第K小+区间不同值个数)的相关文章

HDU 5919 Sequence II(主席树+逆序思想)

Sequence II Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 1422    Accepted Submission(s): 362 Problem Description Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2

HDU 5919 Sequence II 主席树

Sequence II Problem Description Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2,?,an There are m queries. In the i-th query, you are given two integers li and ri. Consider the subsequence ali,ali+1,ali+2,?,ari. We can deno

HDU 5919 -- Sequence II (主席树)

题意: 给一串数字,每个数字的位置是这个数第一次出现的位置. 每个询问对于序列的一个子区间,设一共有k个不同的数,求第ceil(k/2)个数的位置. 因为强制在线,所以离线乱搞pass掉. 主席树可解. 考虑一个数列: p      1 2 3 4 5 6  // 原序列标号 a : 1 2 1 2 3 4  // 原序列 p1 1 2 1 2 5 6  // 子序列开始下标为1 p2        2 3 1 5 6 p3           3 4 5 6 p4              4

HDU 5919 Sequence II(主席树)题解

题意:有A1 ~ An组成的数组,给你l r,L = min((l + ans[i - 1]) % n + 1, (r + ans[i - 1]) % n + 1),R = max((l + ans[i - 1]) % n + 1, (r + ans[i - 1]) % n + 1),你先需要的到L,R区间有k个不同的数字,然后问你L,R区间第(k + 1)/ 2个不同的数字下标是多少? 思路:显然是个在线询问. 我们之前已经会用主席树求区间内有多少不同数字了:从左到右把每个数字的位置存进每个操

HDU 5919 Sequence II

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5919 ------------------------------------------------------------------------------------ 现场赛的时候由于不会主席树就用分块卡过去了 现在学习了主席树后感觉这题也是很有意思的 首先 这题要把问题转化为对于一段区间 求一个左端点相同的$($如果有多个取右端点最靠左的$)$子区间 这个子区间的不同数的个数等于原区间不同

hdu 5147 Sequence II(树状数组)

题目链接:hdu 5147 Sequence II 预处理每个位置作为b和c可以组成的对数,然后枚举b的位置计算. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 50005; int N, arr[maxn], fenw[maxn], lef[maxn], rig[maxn]; #d

poj 2104主席树求区间第k小

POJ - 2104 题意:求区间第k小 思路:无修改主席树 AC代码: #include "iostream" #include "iomanip" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set&

zoj 2112 Dynamic Rankings(主席树&amp;动态第k大)

Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They

少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小

少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小 有一道题(BZOJ 1901)是这样的:n个数,m个询问,询问有两种:修改某个数/询问区间第k小. 不带修改的区间第k小用主席树很好写,不会的同学可以看一下这个. 加上修改怎么做呢?我们可以用数学老师成天讲的类比思想: 可以发现,不修改的区间k小问题中,每加入一个原序列中的数,对应的主席树在上一个的基础上进行修改,而查询的时候用右端点主席树减去左端点左边的主席树.这样的操作就像是维护前缀和:每次加入一个元素的时候,sum[i] =