题目链接:点我~~
题意:给定一个序列n
,有m
次查询,每次查询一个区间[l,r]
,求区间中每一种数在区间中第一次出现的位置的中位数,强制在线。
思路:
主席树维护后缀[i,n],然后对于每次碰到一个数字,就把它以前的位置−1,新位置+1
主席树维护区间不同数字的个数k
然后寻找区间第k/2大呗
因为是维护的后缀,直接找root[l]里的第k/2大出现的位置就行了
当对某版本进行多次单点更新的时候,每次都需要新增一条路径,必须保证不对以往的版本造成影响。
#include <bits/stdc++.h> using namespace std; #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) #define vecotr vector typedef vector<int> VI; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII; typedef pair<double,double> PDD; const int mod=1e9+7; const double eps=1e-8; const int inf=0x3f3f3f3f; const double pi=acos(-1.0); //LL powmod(LL a,LL b) {LL res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} const int MAXN = 200010; const int M = MAXN * 100; int n,q,tot; int a[MAXN]; int T[MAXN],lson[M],rson[M],c[M]; int build(int l,int r) { int root = tot++; c[root] = 0; if(l != r) { int mid = (l+r)>>1; lson[root] = build(l,mid); rson[root] = build(mid+1,r); } return root; } int update(int root,int pos,int val) { int newroot = tot++, tmp = newroot; c[newroot] = c[root] + val; int l = 1, r = n; while(l < r) { int mid = (l+r)>>1; if(pos <= mid) { lson[newroot] = tot++; rson[newroot] = rson[root]; newroot = lson[newroot]; root = lson[root]; r = mid; } else { rson[newroot] = tot++; lson[newroot] = lson[root]; newroot = rson[newroot]; root = rson[root]; l = mid+1; } c[newroot] = c[root] + val; } return tmp; } int query(int root,int pos) { int ret = 0; int l = 1, r = n; while(pos < r) { int mid = (l+r)>>1; if(pos <= mid) { r = mid; root = lson[root]; } else { ret += c[lson[root]]; root = rson[root]; l = mid+1; } } return ret + c[root]; } int finds(int x,int l,int r,int k) { if(l == r) return l; int mid = l + r >> 1; if(c[lson[x]] >= k) return finds(lson[x],l,mid,k); else return finds(rson[x],mid+1,r,k-c[lson[x]]); } int ans[MAXN]; int main() { int t; scanf("%d",&t); int casee=1; while(t--) { scanf("%d%d",&n,&q); tot = 0; for(int i = 1; i <= n; i++) scanf("%d",&a[i]); T[n+1] = build(1,n); map<int,int>mp; for(int i = n; i>= 1; i--) { if(mp.find(a[i]) == mp.end()) { T[i] = update(T[i+1],i,1); } else { int tmp = update(T[i+1],mp[a[i]],-1); T[i] = update(tmp,i,1); } mp[a[i]] = i; } int last=0; int tol=0; while(q--) { int l,r; scanf("%d%d",&l,&r); l=(l+last)%n+1; r=(r+last)%n+1; if(r<l) swap(l,r); last=query(T[l],r)+1>>1; last=finds(T[l],1,n,last); ans[tol++]=last; } printf("Case #%d:",casee++); int len=tol; for(int i=0; i<tol; ++i) printf(" %d",ans[i]); puts(""); } return 0; } /* 2 5 2 3 3 1 5 4 2 2 4 4 5 2 2 5 2 1 2 2 3 2 4 */
- 版权声明:本文基于《知识共享署名-相同方式共享 3.0 中国大陆许可协议》发布,转载请遵循本协议
- 文章链接:http://www.carlstedt.cn/archives/1268 (转载时请注明本文出处及文章链接)
发表评论
快来吐槽一下吧!