首页 > 其他分享 >Codeforces Round 406 (Div. 1) C. Till I Collapse 主席树上二分

Codeforces Round 406 (Div. 1) C. Till I Collapse 主席树上二分

时间:2023-03-16 18:23:03浏览次数:44  
标签:二分 Collapse int 复杂度 Codeforces Till maxn logN 主席

首先贪心是显然的,但是询问有n个

先考虑一个朴素的主席树做法

对于每个k,对于当前固定的L,二分R,用主席树查询一下[L,R]区间内的不同数个数是否大于K个(主席树的经典应用),更新答案,暴力跳过去

时间复杂度:一共有nlogN个区间(n/1+n/2+n/3~nlnN,调和级数知识)

二分的复杂度是logN,主席树查询的复杂度是logN,一共是N*(logN)^3,GET TLE!

////////////

"如果能省去二分的复杂度,在主席树上直接二分就很好了!"

参考别的博客有一个trick:倒序建主席树,第i棵主席树管理的是[i,n]之间有多少不同数

对于当前的a[i],它有效的区间其实是[ i, last[a[i]]-1 ] ,因为再往后,它已经出现过了,贡献都是一样的

区间更新的话同样差分就可以解决(可以参考主席树入门:求静态区间第k小)

经过这样的转换后查询r时直接在主席树上二分即可

对于当前结点的左子树,如果其cnt>k,则递归到左边;否则递归到右边

 

 

 

 

#include<bits/stdc++.h>
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int maxn=1e5+5;
const int N=maxn<<6;
int n;
int node,rt[N];
struct tree{
    int ls,rs,cnt;
}t[N];
void update(int& p,int pos,int val,int l=1,int r=n+1){
    t[++node]=t[p];t[node].cnt+=val;p=node;
    if(l==r){
        return;
    }
    int mid=l+r>>1;
    if(pos<=mid) update(t[p].ls,pos,val,l,mid);
    else update(t[p].rs,pos,val,mid+1,r);
}
int query(int kth,int x,int l=1,int r=n+1){
    if(l==r){
        return l;
    }
    int mid=l+r>>1;
    int sum=t[t[x].ls].cnt;
    //cout<<"kth: "<<kth<<" x: "<<x<<" sum: "<<sum<<" "<<" [l,r]:"<<l<<" "<<r<<endl;
    if(sum>kth) return query(kth,t[x].ls,l,mid);
    else return query(kth-sum,t[x].rs,mid+1,r);
} 
int a[maxn],last[maxn];
int main(){
    fastio;
    //freopen("lys.in","r",stdin);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    update(rt[n],n,1);
    last[a[n]]=n;
    for(int i=n-1;i>=1;i--){
        //cout<<i<<" th"<<endl;
        rt[i]=rt[i+1];
        update(rt[i],i,1);
        if(last[a[i]]){
            update(rt[i],last[a[i]],-1);
        }
        last[a[i]]=i;
    }
    for(int i=1;i<=n;i++){
        int j=1,ans=0;
        while(j<=n){
            //cout<<"j: "<<j<<endl;
            j=query(i,rt[j]);
            ans++;
        }
        cout<<ans<<" ";
    } 
}

 

标签:二分,Collapse,int,复杂度,Codeforces,Till,maxn,logN,主席
From: https://www.cnblogs.com/liyishui2003/p/17223744.html

相关文章

  • Educational Codeforces Round 2 E Lomsat gelral 线段树合并
    题目链接大致题意给你一棵有n个点的树,树上每个节点都有一种颜色ci(ci≤n),让你求每个点子树出现最多的颜色/编号的和记性不好,主要是为了防止自己忘掉,今天和队友合作写题......
  • Codeforces Round 855 (Div. 3)
    之前立下了一个flag,每个有空的下午做一套CF来增长智商。题目地址G.Symmetree问题的本质如何快速比对两个子树是否相同。考虑树hash。这里采用的是主流的AHU算法(安徽......
  • Codeforces Round 857 (Div. 2) A. Likes
    linkCode//#include<bits/stdc++.h>#include<iostream>#include<cstring>#include<algorithm>#include<vector>#include<queue>#include<cmath>#include......
  • Educational Codeforces Round 105 (Rated for Div
    EducationalCodeforcesRound105(RatedforDiv.2)ABCString给定一个字符串只有A、B和C构成。要求替换A、B、C为')'和'(',并且相同字母替换的是一样的,使得字符串变......
  • Codeforces Round 713 (Div
    CodeforcesRound713(Div.3)A-BPalindrome给定字符串只含有\('?'\'0'\'1'\),给定字符串中1的个数\(a\)和0的个数\(b\),你需要将?替换成0或1,使得该字符串变成回文......
  • Codeforces Round 857 (Div. 2)
    比赛地址做到F心态崩了,自然不会去做G.F考虑最终路径一定是这样的1到x节点在x处攒够路费再到n.后者可以通过从n跑dij来求最短路。考虑前者需要求从1~x的最小代价。......
  • CodeForces 1147F Zigzag Game
    洛谷传送门CF传送门很有意思的题。考虑若无边权的限制则B必胜,不妨猜想有了限制之后仍然是B必胜。假设A选了I(若A选了D可以边权取相反数),若B走了\((a,b)\)......
  • Codeforces Round 857 (Div. 2)
    题目链接A核心思路读懂题目也就不难了。//Problem:A.Likes//Contest:Codeforces-CodeforcesRound857(Div.2)//URL:https://codeforces.com/contest/180......
  • Codeforces比赛规则梳理
    1、排名div选手们按Rating以1700为界划分为Div.1和Div.2两类,Div.1的比赛较难,Div.1的ABC三题会和Div.2的CDE三题相同。每次比赛结束后Rating都会依据此前各个选手的Rating和......
  • Codeforces Round #666 (Div. 2)D. Stoned Game(博弈问题)
    problemT和HL玩游戏,n堆石头,玩家轮流在石堆中选择一个(但不能是上一个人取的那堆)取一个石子一旦有一方不能取石头则判输solution统计所有石头数,如果总数小于mx(最多石头的一堆)......