Irrigation

 

 

题意:有一个长度为m的计数数组a,初始均为0,并给定前n个操作x表示让a[x]加1. 现在还有一些操作,一个操作是在a[1~m]中找一个a[p]值最小的位置p(有多个则取最小的满足条件的p)使得a[p]加1,现在有q个询问,问第k次操作时的p.

首先考虑把前n次操作后的a数组按照a[i]的值从小到大排个序(当然如果大小相等编号小的在前)然后考虑每一个操作,当最低点有k个的时候,必然是每k个操作一个循环节,并且会循环总共a[k+1]−a[k]次之后最低点增加.

有了这个性质之后,就可以把它分成m部分分别求解,其中第i部分是把前i小的数填到第i+1小的数的过程.

可以考虑依次枚举每一部分,然后求解这一部分内的询问,并且维护每一部分开始时的操作次数,用当前询问的k减掉当前这个操作次数之后我们就得到了它是这个部分操作时的第几个操作,
由于每一个部分内的操作是循环的,我们就可以通过取模得到它是这个操作可以影响到的数中第几小的.
然后问题转化为了如何维护第k小

AC_Code

 1 //注意一始tree都为0
 2 utm_source=distribute.pc_relevant.none-task
 3 #include <bits/stdc++.h>
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn = 5e5+10;
 7 #define rep(i,first,last) for(int i=first;i<=last;i++)
 8 #define dep(i,first,last) for(int i=first;i>=last;i--)
 9 struct city{int id;int cnt;}a[maxn];
10 struct pry{int id;ll year;}b[maxn];
11 int n,m,q;
12 int tree[maxn<<2],ans[maxn];
13 bool cmp1(city x, city y){
14     if( x.cnt==y.cnt ) return x.id<y.id;
15     return x.cnt<y.cnt;
16 }
17 
18 bool cmp2(pry x, pry y){
19     return x.year<y.year;
20 }
21 
22 void updata(int rt,int l,int r,int pos){
23     if( l==r ){
24         tree[rt]++;
25         return ;
26     }
27     int mid=(l+r)>>1;
28     if( pos>mid ) updata(rt<<1|1,mid+1,r,pos);
29     else updata(rt<<1,l,mid,pos);
30     tree[rt]=tree[rt<<1]+tree[rt<<1|1];
31 }
32 
33 int Kth(int rt,int l,int r,int k){
34     if( l==r ) return l;
35     int mid=(l+r)>>1;
36     if( tree[rt<<1]<k ) return Kth(rt<<1|1,mid+1,r,k-tree[rt<<1]);
37     else return Kth(rt<<1,l,mid,k);
38 }
39 
40 void solve(){
41     ll now=n;
42     int j=1;
43     rep(i,1,m){
44        ll nxt=i==m?2e18:(ll)(a[i+1].cnt-a[i].cnt)*i+now;
45        updata(1,1,m,a[i].id);
46        while( j<=q && b[j].year<=nxt ){
47             ll year=b[j].year;
48             int idx=(year-now)%i;
49             if( idx==0 ) idx=i;
50             ans[b[j].id]=Kth(1,1,m,idx);
51             j++;
52        }
53        now=nxt;
54     }
55 }
56 
57 int main()
58 {
59     scanf("%d%d%d",&n,&m,&q);
60     rep(i,1,n){
61         int x;
62         scanf("%d",&x);
63         a[x].cnt++;
64     }
65     rep(i,1,m) a[i].id=i;
66     rep(i,1,q){
67         scanf("%lld",&b[i].year);
68         b[i].id=i;
69     }
70     sort(a+1,a+1+m,cmp1);
71     sort(b+1,b+1+q,cmp2);
72     solve();
73     rep(i,1,q){
74         printf("%d
",ans[i]);
75     }
76     return 0;
77 }

参考博客:https://www.cnblogs.com/wzj-xhjbk/p/11039510.html

     https://blog.csdn.net/hzk_cpp/article/details/92797305?utm_source=distribute.pc_relevant.none-task

原文地址:https://www.cnblogs.com/wsy107316/p/12334901.html