zoukankan      html  css  js  c++  java
  • csps模拟68d,e,f题解

    题面:https://www.cnblogs.com/Juve/articles/11655531.html

    三道数据结构?

    d:

    贪心,先按a排序,然后枚举删了前i个a值比较小的,然后在剩下的里面删m-i个b小的,然后统计答案

    用主席树查b排名(m-i+1)或用堆维护b

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define int long long
    using namespace std;
    const int MAXN=1e5+5;
    int read(){
        int x=0;char ch=getchar();
        while(ch<'0'||ch>'9') ch=getchar();
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
        return x;
    }
    int t,n,m,ans;
    struct node{
        int a,b;
        friend bool operator < (node p,node q){
            return p.a<q.a;
        }
    }sq[MAXN];
    priority_queue<int>q;
    signed main(){
        t=read();
        while(t--){
            n=read(),m=read();
            ans=0;
            for(int i=1;i<=n;++i) sq[i].a=read(),sq[i].b=read();
            sort(sq+1,sq+n+1);
            while(!q.empty()) q.pop();
            for(int i=m+1;i<=n;++i) q.push(-sq[i].b);
            for(int i=m;i>=0;--i){
                int mx=-q.top();
                ans=max(ans,mx*sq[i+1].a);
                if(sq[i].b>mx){
                    q.pop();
                    q.push(-sq[i].b);
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define int long long
    using namespace std;
    const int MAXN=1e5+5;
    int read(){
        int x=0;char ch=getchar();
        while(ch<'0'||ch>'9') ch=getchar();
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
        return x;
    }
    int t,n,m,ans,mx=0;
    struct node{
        int a,b;
        friend bool operator < (node p,node q){
            return p.a<q.a;
        }
    }sq[MAXN];
    int root[MAXN],tot=0;
    struct chairman_tree{
        int ls,rs,val;
    }tr[MAXN<<6];
    void insert(int &now,int pre,int l,int r,int pos){
        now=++tot;tr[now]=tr[pre];++tr[now].val;
        if(l==r) return ;
        int mid=(l+r)>>1;
        if(pos<=mid) insert(tr[now].ls,tr[pre].ls,l,mid,pos);
        else insert(tr[now].rs,tr[pre].rs,mid+1,r,pos);
    }
    int query(int x,int y,int l,int r,int num){
        if(l==r) return l;
        int sum=tr[tr[y].ls].val-tr[tr[x].ls].val,mid=(l+r)>>1;
        if(sum>=num) return query(tr[x].ls,tr[y].ls,l,mid,num);
        else return query(tr[x].rs,tr[y].rs,mid+1,r,num-sum);
    }
    signed main(){
        t=read();
        while(t--){
            n=read(),m=read();
            ans=tot=mx=0;
            for(int i=1;i<=n;++i) sq[i].a=read(),sq[i].b=read(),mx=max(mx,sq[i].b);
            sort(sq+1,sq+n+1);
            for(int i=1;i<=n;++i)
                insert(root[i],root[i-1],1,mx,sq[i].b);
            for(int i=0;i<=m;++i)
                ans=max(ans,sq[i+1].a*query(root[i],root[n],1,mx,m-i+1));
            printf("%lld
    ",ans);
        }
        return 0;
    }
    主席树

    e:

    开始学习主席树上树

    不难看出是在每个询问点到所有询问点的lca路径上的前趋后继,然后就打的测试点分治和暴力

    新知识:树上主席树,维护每个节点到根的前缀主席树,然后区间查询前趋后继

    查前趋:

    当前mid比val大,去右区间查找,但是会有一种情况:val等于mid+1,但主席树中没有mid+1,这时特判一下去找左区间

    后继同理

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define int long long
    using namespace std;
    int read(){
    	int x=0;char ch=getchar();
    	while(ch<'0'||ch>'9') ch=getchar();
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
    	return x;
    }
    const int MAXN=1e5+5;
    int n,q,typ,a[MAXN],ans=0,p[MAXN],b[MAXN],mx;
    int to[MAXN<<1],nxt[MAXN<<1],pre[MAXN],cnt=0;
    void add(int u,int v){
    	++cnt,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt;
    }
    int root[MAXN],tot=0;
    struct node{
    	int ls,rs,val;
    }tr[MAXN<<6];
    void insert(int &now,int pre,int l,int r,int val){
    	now=++tot;tr[now]=tr[pre],++tr[now].val;
    	if(l==r) return ;
    	int mid=(l+r)>>1;
    	if(val<=mid) insert(tr[now].ls,tr[pre].ls,l,mid,val);
    	else insert(tr[now].rs,tr[pre].rs,mid+1,r,val);
    }
    int get_pre(int x,int y,int l,int r,int val){
    	if(tr[y].val-tr[x].val==0) return 0;
    	if(l==r) return l;
    	int mid=(l+r)>>1,res=0;
    	if(val>mid){
    		res=get_pre(tr[x].rs,tr[y].rs,mid+1,r,val);
    		if(res==0) res=get_pre(tr[x].ls,tr[y].ls,l,mid,val);
    	}else res=get_pre(tr[x].ls,tr[y].ls,l,mid,val);
    	return res;
    }
    int get_nxt(int x,int y,int l,int r,int val){
    	if(tr[y].val-tr[x].val==0) return 0;
    	if(l==r) return l;
    	int mid=(l+r)>>1,res=0;
    	if(val<=mid){
    		res=get_nxt(tr[x].ls,tr[y].ls,l,mid,val);
    		if(res==0) res=get_nxt(tr[x].rs,tr[y].rs,mid+1,r,val);
    	}else res=get_nxt(tr[x].rs,tr[y].rs,mid+1,r,val);
    	return res;
    }
    int deep[MAXN],fa[MAXN],siz[MAXN],son[MAXN];
    void dfs(int x){
    	siz[x]=1;
    	for(int i=pre[x];i;i=nxt[i]){
    		int y=to[i];
    		if(y==fa[x]) continue;
    		fa[y]=x;
    		deep[y]=deep[x]+1;
    		dfs(y);
    		siz[x]+=siz[y];
    		if(siz[son[x]]<siz[y]) son[x]=y;
    	}
    }
    int top[MAXN];
    void DFS(int x,int topf){
    	insert(root[x],root[fa[x]],1,mx,a[x]);
    	top[x]=topf;
    	if(son[x]) DFS(son[x],topf);
    	for(int i=pre[x];i;i=nxt[i]){
    		int y=to[i];
    		if(y==fa[x]||y==son[x]) continue;
    		DFS(y,y);
    	}
    }
    int LCA(int x,int y){
    	while(top[x]!=top[y]){
    		if(deep[top[x]]<deep[top[y]]) swap(x,y);
    		x=fa[top[x]];
    	}
    	if(deep[x]>deep[y]) swap(x,y);
    	return x;
    }
    signed main(){
    	n=read(),q=read(),typ=read();
    	for(int i=1;i<=n;++i) a[i]=read(),mx=max(mx,a[i]);
    	for(int i=1,u,v;i<n;++i){
    		u=read(),v=read();
    		add(u,v),add(v,u);
    	}
    	dfs(1);DFS(1,1);
    	while(q--){
    		int r=read(),k=read();
    		int lca;
    		for(int i=1;i<=k;++i){
    			p[i]=read();
    			p[i]=(p[i]-1+ans*typ)%n+1;
    			if(i==1) lca=p[i];
    			else lca=LCA(lca,p[i]);
    		}
    		ans=0x3f3f3f3f;
    		for(int i=1;i<=k;++i){
    			int pre=get_pre(root[fa[lca]],root[p[i]],1,mx,r);
    			int nxt=get_nxt(root[fa[lca]],root[p[i]],1,mx,r);
    			if(pre) ans=min(ans,abs(r-pre));
    			if(nxt) ans=min(ans,abs(nxt-r));
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    

    f:

    不会了,打的暴力树状数组逆序对

  • 相关阅读:
    PAT之我要通过
    卡拉兹(Callatz)猜想
    数组元素循环右移问题
    Reorder List
    一个fork的面试题
    内存流和null字节
    标准C IO函数和 内核IO函数 效率(时间)比较
    由fdopen和fopen想到的
    VS经常报错的link error 2019
    VS快捷键设置
  • 原文地址:https://www.cnblogs.com/Juve/p/11655694.html
Copyright © 2011-2022 走看看