首页 > 其他分享 >UNR #7 Day2 T1 火星式选拔题解

UNR #7 Day2 T1 火星式选拔题解

时间:2023-07-18 21:12:38浏览次数:47  
标签:UNR return rs int 题解 Day2 mid tr maxn

放一个比赛链接

先考虑打完暴力后 \(k = 1\) 的特殊性质。

当队列容量为 \(1\) 时,队中的人 \(i\) 会被第一个满足 \(i \leq j\) 且 \(b_i \leq a_j\) 的人淘汰,并且队列中的人会变成 \(j\),考虑倍增加速这个过程,令 \(f_{i,j}\) 表示第 \(i\) 个人进队后淘汰过程发生 \(2^j\) 次后队中的人,答案就是 \(\max_{f_{l,i} \leq r}(f_{l,i})\),我们预处理 ST 表二分求出 \(f_{i,0}\) 在递推即可求出 \(f\) 数组,所以总时间是 \(O(n \log n)\) 的。

接着手玩几组数据,发现 \(b_i\) 较大的几个人总是不会被淘汰,这是为什么?

我们发现因为每次假若要淘汰只会淘汰 \(b_i\) 最小的,而区间中 \(b_i\) 前 \(k-1\) 大的人 一定不会成为最小的,所以我们可以确定区间中 \(b_i\) 前 \(k-1\) 大的人一定在队中, 并且不是排名最后的一个人

考虑怎么求最后一个人。

令区间 \(b_i\) 前 \(k-1\) 大的人全部入队时考虑到第 \(x\) 个人,那么我们发现在考虑第 \(x-1\) 个人时,区间 \([l,x-1]\) 中前 \(k-1\) 大一定也在队中,那么第 \(x\) 个人实际上就是淘汰了考虑第 \(x-1\) 个人时队列中最后一个人,因此,区间 \([l,x-1]\) 中第 \(k-1\) 大的人因为不是排名最后的一个人,所以就会被保留在队中。也就是说此时队列中最后一个人是区间 \([l,x-1]\) 中第 \(k-1\) 大!

然后考虑这个人会不会被淘汰,假若被淘汰那么此时问题变成一个与 \(k=1\) 相似的问题,就从淘汰此人的人开始倍增往后面跳。

最后用主席树维护区间,这道题目就解决了。

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
const int maxn = 5e5+114;
int a[maxn],b[maxn],f[maxn][21];
long long c[maxn];
int st[maxn][21][2];
int lg[maxn];
int n,q;
inline void init(){
	 for(int i=1;i<=n;i++) st[i][0][0]=a[i],st[i][0][1]=b[i];
  		for(int j=1;j<=lg[n];j++)
    		for(int i=1;i+(1<<j)-1<=n;i++)
    			st[i][j][0]=max(st[i][j-1][0],st[i+(1<<(j-1))][j-1][0]),st[i][j][1]=max(st[i][j-1][1],st[i+(1<<(j-1))][j-1][1]);
}
inline int qmx(int l,int r,int type){
    if(l>r) return 0;
    int k=lg[r-l+1]; 
    return max(st[l][k][type],st[r-(1<<k)+1][k][type]);
}
inline int ask(int l,int r){
	for(int i=20;i>=0;i--){
		if(f[l][i]<=r&&f[l][i]!=0){
			l=f[l][i];
		}
	}
	return l;
}
struct Node{
    int sum,ls,rs;
    long long val;
}tr[maxn*22];
int root[maxn],tot;
int g[maxn];
inline void add(int cur,int lst,int lt,int rt,int pos){
    tr[cur].sum=tr[lst].sum+1;
    tr[cur].val=tr[lst].val+c[g[pos]];
    if(lt==rt){
        return ;
    }
    int mid=(lt+rt)>>1;
    if(pos<=mid){
        tr[cur].rs=tr[lst].rs;
        tr[cur].ls=++tot;
        add(tr[cur].ls,tr[lst].ls,lt,mid,pos);
    }
    else{
        tr[cur].ls=tr[lst].ls;
        tr[cur].rs=++tot;
        add(tr[cur].rs,tr[lst].rs,mid+1,rt,pos);
    }
}
inline long long query(int ql,int qr,int lt,int rt,int L,int R){
	if(ql>qr) return 0;
    if(rt<ql||lt>qr){
        return 0;
    }
    if(ql<=lt&&rt<=qr){
        return tr[R].val-tr[L].val;
    }
    int mid=(lt+rt)>>1;
    long long res=0;
    res+=query(ql,qr,lt,mid,tr[L].ls,tr[R].ls);
    res+=query(ql,qr,mid+1,rt,tr[L].rs,tr[R].rs);
    return res;
}
inline int kth(int lt,int rt,int L,int R,int k){
    if(lt==rt) return lt;
    int mid=(lt+rt)>>1;
    if((tr[tr[R].rs].sum-tr[tr[L].rs].sum)>=k){
        return kth(mid+1,rt,tr[L].rs,tr[R].rs,k);
    }
    else{
        return kth(lt,mid,tr[L].ls,tr[R].ls,k-(tr[tr[R].rs].sum-tr[tr[L].rs].sum));
    }
}
inline int ChiFAN(int l,int r,int x){
    int L=l,R=r+1;
    while(L+1<R){
        int mid=(L+R)>>1;
        if(qmx(mid,r,1)<x){
            R=mid;
        }
        else{
            L=mid;
        }
    }
    return L;
}//第 k-1 个大出现的地方
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    lg[0]=1;
    for(int i=1;i<maxn;i++) lg[i]=log2(i);
	cin>>n>>q;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>b[i];
    for(int i=1;i<=n;i++) g[b[i]]=i;
    for(int i=1;i<=n;i++) cin>>c[i];
	init();
    for(int i=1;i<=n;i++){
        root[i]=++tot;
        add(root[i],root[i-1],1,n,b[i]);
    }
	for(int i=1;i<=n;i++){
		int l=i,r=n;
		if(qmx(i+1,n,0)<b[i]){
			f[i][0]=n+1;
			continue ;
		}
		while(l+1<r){
			int mid=(l+r)>>1;
			if(qmx(i+1,mid,0)>=b[i]){
				r=mid;
			}
			else{
				l=mid;
			}
		}
		f[i][0]=r;
	}
	for(int j=1;j<=20;j++){
		for(int i=1;i<=n;i++){
			f[i][j]=f[f[i][j-1]][j-1];
		}
	}
	while(q--){
        int l,r,k;
        cin>>l>>r>>k;
        if(k==1){
            cout<<c[ask(l,r)]<<'\n';
        }
        else{
            int p=g[kth(1,n,root[l-1],root[r],k-1)];
            int e=ChiFAN(l,r,b[p]);
            int t=g[kth(1,n,root[l-1],root[e-1],k-1)];
            if(qmx(e+1,r,0)>=b[t]){
                int L=e,R=r;
                while(L+1<R){
                    int mid=(L+R)>>1;
                    if(qmx(e+1,mid,0)>=b[t]){
                        R=mid;
                    }
                    else{
                        L=mid;
                    }
                }
                t=R;
                for(int i=20;i>=0;i--){
                    if(f[t][i]<=r&&f[t][i]!=0) t=f[t][i];
                }
            }
            cout<<query(b[p],n,1,n,root[l-1],root[r])+c[t]<<'\n';
        }
    }
}

标签:UNR,return,rs,int,题解,Day2,mid,tr,maxn
From: https://www.cnblogs.com/chifan-duck/p/17564134.html

相关文章

  • P6684 题解
    真的卡不动了,但是我感觉我的思路还是有一些价值的,就来写一篇题解吧。考虑使用回滚莫队(不增)来维护,当区间删去一个点时相当于全局加入一条边,这个询问的本质是询问是否是二分图,所以考虑扩展值域并查集,这里使用路径压缩加按秩合并,记录下修改,在回滚时全部还原。总复杂度是\(O(n\sqr......
  • 「JOISC 2019 Day4」蛋糕拼接 3 题解
    先考虑这个式子:\(\sum_{j=1}^{M}|C_{k_{j}}-C_{k_{j+1}}|\)一定是在\(C\)有序时取到,具体证明很简单各位读者自己证明。那么现在式子变成:\(\sum{V}+2\times({C_{\max}-C_{\min}})\)这个时候一个常见的技巧是将\(C\)排序。这个时候就可以定义状态:\(dp_{i,j}=\s......
  • 【UNR #7】比特迷宫
    Description小青鱼来到了重(zhòng)庆市的一个迷宫,名为比特迷宫。听说只有最聪明的人才能从里面走出。这个迷宫看似容易,但在小青鱼即将走出迷宫的时候,却被\(n=2^k\)个比特机器人拦住了去路。这些机器人从左到右显示着\(a_{0,},a_1,\cdots,a_{n-1},\)表示一个\(n-1\)......
  • CF1438F 题解
    problem&blog。神秘随机题。众所周知:\((u,v)\)的LCA是所有点\(i\)中\(\operatorname{dis}(u,i)+\operatorname{dis}(v,i)+\operatorname{dis}(\text{root},i)\)最小的。对于一个点\(u\),设其有两个子树\(T_1,T_2\),它能作为LCA的方案数是\(|T_1|\times|T_2|\ti......
  • 算法练习-day20
    二叉树669.修剪二叉搜索树题意:给你二叉搜索树的根节点root,同时给定最小边界low和最大边界high。通过修剪二叉搜索树,使得所有节点的值在[low,high]中。修剪树不应该 改变保留在树中的元素的相对结构(即如果没有被移除,原有的父代子代关系都应当保留)。可以证明,存在唯一的答案 ......
  • CF1769C2 Подкрутка II 题解
    看到同机房的好哥们发了贪心做法的题解,心血来潮就A了这道题写了真·dp的题解。虽然方法比老师上课讲的麻烦的多,并不是最优解,但至少是我自己思考得出的结果。题目要求输入一个原序列\(a_i\),从\(a_i\)中求得某个区间\([l,r]\)。此区间经过题面中所描述的修改操作(任何元素\(......
  • P6835 [Cnoi2020] 线形生物题解
    P6835[Cnoi2020]线形生物题解题目描述求从\(1\)到\(n+1\)的链的期望,其中有\(m\)条返祖边:\(u->v\)这条边\(u\gev\),等概率,求期望Solution这种爬楼梯的题一般求解\(E(x\rightarrowx+1)\),则最后答案为\(\sum_{i=1}^nE(i\rightarrowi+1)\)我们考虑从\(x\rightarr......
  • Building Bridges 题解
    BuildingBridges题目大意连接两根柱子\(i,j\)的代价是\((h_i-h_j)^2+\sum\limits_{k=j+1}^{i-1}w_k\),连接具有传递性,求将\(1,n\)连接的最小代价。思路分析斜率优化DP板题。设\(f_i\)表示考虑到前\(i\)根柱子并强制选择第\(i\)根柱子的最小代价,所求即\(f_n\)。......
  • [ABC310D] Peaceful Teams 题解
    PeacefulTeams题目大意将\(n\)个人分成\(T\)组,要求每组不能包含敌对的人,问有多少种分法。思路分析注意到\(n,T\)均很小,考虑爆搜。注意到直接枚举会枚举到分组顺序的全排列,所以可以强行嵌定大小关系去重。voiddfs(ints){if(s==n+1){for(inti=1;i<=t;......
  • unraid配置设置开启vpη WireGuard隧道peer
    unraid6.12版本自带WireGuard,在外访问家庭设备iosiPhone第一步,路由器打开51820端口,并添加端口转发到unraid第二步,设置-vpη管理器添加,填写名称和本地端点即可,需要当前公网ip或者ddns的域名,还没有ddns的博主推荐namesilo-ddns接着添加peer,只需填写名称和类型即可点击应......