• HDU 5919 Sequence II(主席树+区间不同数个数+区间第k小)


    http://acm.split.hdu.edu.cn/showproblem.php?pid=5919

    题意:
    给出一串序列,每次给出区间,求出该区间内不同数的个数k和第一个数出现的位置(将这些位置组成一个新的序列),输出这里面的第ceil(k/2)个数。

    思路:

    因为每个区间只需要统计第一个数出现的位置,那么从右往左来建树,如果该数没有出现,那么就将该位置+1,否则要将上一次出现的位置-1后再在该位置+1。

    统计不同数的个数很简单,就是线段树查询。

    查询出第k小的数也很简单,因为我们是从后往前建树的,那么t[l]这棵树里面的元素就是从l开始的数组,直接线段树查询第k个数即可。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #include<stack>
      7 #include<queue>
      8 #include<cmath>
      9 #include<map>
     10 #include<set>
     11 using namespace std;
     12 typedef long long ll;
     13 typedef pair<int,int> pll;
     14 const int INF = 0x3f3f3f3f;
     15 const int maxn = 2*1e5+5;
     16 
     17 int tot,n,m;
     18 int a[maxn],pre[maxn],rot[maxn];
     19 
     20 struct node
     21 {
     22     int l,r,num;
     23 }t[maxn*50];
     24 
     25 int build(int l, int r)
     26 {
     27     int root=++tot;
     28     t[root].num=0;
     29     if(l==r)  return root;
     30     int mid=(l+r)>>1;
     31     t[root].l=build(l,mid);
     32     t[root].r=build(mid+1,r);
     33     return root;
     34 }
     35 
     36 int update(int root, int pos, int d)
     37 {
     38     int now = ++tot;
     39     int tmp = now;
     40     t[tot].num = t[root].num + d;
     41     int l = 1, r = n;
     42     while(l<r)
     43     {
     44         int mid = (l+r)>>1;
     45         if(pos<=mid)
     46         {
     47             t[now].l = ++tot;
     48             t[now].r = t[root].r;
     49             root = t[root].l;
     50             now = tot;
     51             r = mid;
     52         }
     53         else
     54         {
     55             t[now].l = t[root].l;
     56             t[now].r = ++tot;
     57             root = t[root].r;
     58             now = tot;
     59             l = mid + 1;
     60         }
     61         t[now].num = t[root].num + d;
     62     }
     63     return tmp;
     64 }
     65 
     66 int query(int ql ,int qr, int l, int r, int root)
     67 {
     68     if(ql<=l && qr>=r)  return t[root].num;
     69     int mid = (l+r)>>1;
     70     int ans = 0;
     71     if(ql<=mid)  ans+=query(ql,qr,l,mid,t[root].l);
     72     if(qr>mid)   ans+=query(ql,qr,mid+1,r,t[root].r);
     73     return ans;
     74 }
     75 
     76 
     77 int calc(int l,int r,int k,int root)
     78 {
     79     if(l==r)  return l;
     80     int mid = (l+r)>>1;
     81     if(t[t[root].l].num>=k)  return calc(l,mid,k,t[root].l);
     82     else return calc(mid+1,r,k-t[t[root].l].num,t[root].r);
     83 }
     84 
     85 int main()
     86 {
     87     //freopen("in.txt","r",stdin);
     88     int T;
     89     int kase = 0;
     90     scanf("%d",&T);
     91     while(T--)
     92     {
     93         tot=0;
     94         int bef=0;
     95         memset(pre,-1,sizeof(pre));
     96         scanf("%d%d",&n,&m);
     97         for(int i=1;i<=n;i++)  scanf("%d",&a[i]);
     98         rot[n+1] = build(1,n);
     99         for(int i=n;i>0;i--)
    100         {
    101             if(pre[a[i]] == -1)  rot[i] = update(rot[i+1],i,1);
    102             else
    103             {
    104                 int tmp = update(rot[i+1],pre[a[i]],-1);
    105                 rot[i] = update(tmp,i,1);
    106             }
    107             pre[a[i]] = i ;
    108         }
    109         printf("Case #%d:",++kase);
    110         while(m--)
    111         {
    112             int l,r;
    113             scanf("%d%d",&l,&r);
    114             int ll = (l + bef)%n + 1;
    115             int rr = (r + bef)%n + 1;
    116             l = min(ll, rr);
    117             r = max(ll, rr);
    118             int k = query(l,r,1,n,rot[l]);
    119             k = ceil(k/2.0);
    120             int ans = calc(1,n,k,rot[l]);
    121             bef = ans;
    122             printf(" %d",ans);
    123         }
    124         puts("");
    125     }
    126     return 0;
    127 }
  • 相关阅读:
    转自 Because of you 的总结
    转自 Good morning 的几句精辟的话
    (转)一句话小结各种网络流)
    上下界网络流总结
    浮云洲之战
    Poj3680 Intervals
    NOI2008假面舞会
    NOI2010航空管制
    python爬虫之反爬虫(随机user-agent,获取代理ip,检测代理ip可用性)
    python爬虫之反爬虫(随机user-agent,获取代理ip,检测代理ip可用性)
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7674325.html
Copyright © 2020-2023  润新知