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:

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

  • 相关阅读:
    Attach Files to Objects 将文件附加到对象
    Provide Several View Variants for End-Users 为最终用户提供多个视图变体
    Audit Object Changes 审核对象更改
    Toggle the WinForms Ribbon Interface 切换 WinForms 功能区界面
    Change Style of Navigation Items 更改导航项的样式
    Apply Grouping to List View Data 将分组应用于列表视图数据
    Choose the WinForms UI Type 选择 WinForms UI 类型
    Filter List Views 筛选器列表视图
    Make a List View Editable 使列表视图可编辑
    Add a Preview to a List View将预览添加到列表视图
  • 原文地址:https://www.cnblogs.com/Juve/p/11655694.html
Copyright © 2011-2022 走看看