zoukankan      html  css  js  c++  java
  • noip模拟测试22

    考试总结:这次考试题,有好多部分分,导致了我在考试过程中一心想拿到这些部分分,对于正解没有留出时间进行思考,这是一个教训,在以后的考试中我一定要留出足够的思考时间,不要被部分分限制。还有,我的部分分也没有拿满,犯了一些zz的错误,有因为数组开小的,还有没有控制好优先级的(对于特殊性质的特殊解法),还有自己没有验证正确性的一些暴力优化,还遇到了一个因为我懒,没去学的知识点(痛失20分)。总体来说,这次考试我暴露出的问题有许多,在以后的考试中我会进行改正。

    T1 d

    思路:很显然,我们要求矩形并起来的最大值,就要去掉最多的 x,y,最小的矩形,那么我们可以将 x,预处理排序v,同时用一个优先队列维护 y ,这样我们刚开始假设去掉 m 个 x,接着我们不断将 x 放回,并去掉 y 更新答案即可。
    代码如下:

    AC_Code
    #include<bits/stdc++.h>
    #define int long long
    #define re register int
    #define lc rt<<1
    #define rc rt<<1|1
    #define mid ((l+r)>>1)
    #define re register int
    #define ii inline int
    #define iv inline void
    using namespace std;
    const int N=1e5+10;
    const int INF=1e9+10;
    int t,n,m,ans;
    struct C1
    {
    	int a,pos;
    }u1[N];
    struct C2
    {
    	int b,pos;
    	friend bool operator < (C2 x,C2 y)
    	{
    		return x.b>y.b;
    	}
    }u2[N];
    priority_queue<C2> q;
    bool vis[N],v2[N];
    ii my1(C1 a,C1 b)
    {
    	return a.a<b.a;
    }
    ii read()
    {
    	int x=0,f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-')
    			f=0;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return (f)?x:(-x);
    }
    signed main()
    {
    	t=read();
    	long long minn_a,minn_b;
    	if(t==0)
    		return 0;
    	while(t--)
    	{
    		n=read();
    		m=read();
    		ans=0;
    		minn_a=INF;
    		minn_b=INF;
    		for(re i=1;i<=n;i++)
    		{
    			u1[i].a=read();
    			u2[i].b=read();
    			u1[i].pos=u2[i].pos=i;
    		}
    		sort(u1+1,u1+n+1,my1);
    		memset(vis,0,sizeof(vis));
    		memset(v2,0,sizeof(v2));
    		while(!q.empty())
    			q.pop();
    		for(re i=1;i<=m;i++)
    			vis[u1[i].pos]=1;
    		for(re i=m+1;i<=n;i++)
    			q.push((C2){u2[u1[i].pos].b,u1[i].pos});
    		ans=u1[m+1].a*q.top().b;
    		for(re i=m;i;i--)
    		{
    			vis[u1[i].pos]=0;
    			minn_a=u1[i].a;
    			q.push((C2){u2[u1[i].pos].b,u1[i].pos});
    			v2[q.top().pos]=1;
    			q.pop();
    			minn_b=q.top().b;
    			if(v2[u1[i].pos])
    				continue;
    			ans=max(ans,minn_a*minn_b);
    		}
    		printf("%lld\n",ans);
    	}
    	return 0;
    }
    
    

    T2 e

    思路:很显然,我们需要一种可以维护一条链上信息的数据结构,主席树,那么我们只需要求出所有点的lca,然后分别以这两个点对应的树求出 r 对应的rank,那么我们再通过查询树中 排名为 (rank-1),(rank),(rank+1)的数值进行计算,最后取min即可,注意,在查询的时候有一些细节,当 rank,rank-1,rank+1,<=0或 >sum[lca]-sum[p]的时候我们就不能进行查询,具体实现见代码:
    (因为我们要找的是小于r的最大值和大于r的最小值,所以还有另一种打法 hzoi-fengwu

    AC_Code
    #include<bits/stdc++.h>
    #define int long long
    #define re register int
    #define ii inline int
    #define iv inline void
    #define mid ((l+r)>>1)
    using namespace std;
    const int N=5e5+10;
    const int INF=1e9+10;
    vector<int> v[N];
    int n,q,type,tot,timi,r,ans,k,cnt,jk;
    int a[N],to[N<<1],next[N<<1],head[N],cun_k[N],lsh[N<<4],rt[N],cun_r[N];
    int deep[N],son[N],size[N],num[N],zh[N],fa[N],top[N];
    struct CUN
    {
    	int ls,rs,sum;
    }use[N*80];
    ii read()
    {
    	int x=0,f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-')
    			f=0;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return (f)?x:(-x);
    }
    struct Segment_Tree
    {
    	ii insert(int now,int l,int r,int zh)
    	{
    		int p=++jk;
    		use[p]=use[now];
    		if(l==r)
    		{
    			use[p].sum++;
    			return p;
    		}
    		if(mid>=zh)
    			use[p].ls=insert(use[now].ls,l,mid,zh);
    		else
    			use[p].rs=insert(use[now].rs,mid+1,r,zh);
    		use[p].sum=use[use[p].ls].sum+use[use[p].rs].sum;
    		return p;
    	}
    	ii gett(int x,int y)
    	{
    		int fx=top[x],fy=top[y];
    		while(fx!=fy)
    		{
    			if(deep[fx]<deep[fy])
    			{
    				swap(fx,fy);
    				swap(x,y);
    			}
    			x=fa[fx];
    			fx=top[x];
    		}
    		return (deep[x]<deep[y])?x:y;
    	}
    	ii query_rank(int last,int now,int l,int r,int zh)
    	{
    		if(l==r)
    			return 0;
    		int sum=use[use[now].ls].sum-use[use[last].ls].sum;
    		if(mid>=zh)	return query_rank(use[last].ls,use[now].ls,l,mid,zh);
    		return sum+query_rank(use[last].rs,use[now].rs,mid+1,r,zh);
    	}
    	ii query(int last,int now,int l,int r,int rk)
    	{
    		if(l==r)
    			return l;
    		int sum=use[use[now].ls].sum-use[use[last].ls].sum;
    		if(sum>=rk)	return query(use[last].ls,use[now].ls,l,mid,rk);
    		return query(use[last].rs,use[now].rs,mid+1,r,rk-sum);
    	}
    }T;
    iv add(int x,int y)
    {
    	to[++tot]=y;
    	next[tot]=head[x];
    	head[x]=tot;
    }
    iv dfs(int st,int f)
    {
    	num[st]=++timi;
    	zh[timi]=a[st];
    	size[st]=1;
    	deep[st]=deep[f]+1;
    	for(re i=head[st];i;i=next[i])
    	{
    		int p=to[i];
    		if(p==f)
    			continue;
    		fa[p]=st;
    		dfs(p,st);
    		size[st]+=size[p];
    		son[st]=(size[son[st]]>size[p])?son[st]:p;
    	}
    }
    iv dfs2(int st,int t)
    {
    	top[st]=t;
    	if(!son[st])
    		return;
    	dfs2(son[st],t);
    	for(re i=head[st];i;i=next[i])
    	{
    		int p=to[i];
    		if(p==fa[st]||p==son[st])
    			continue;
    		dfs2(p,p);
    	}
    }
    iv dfs3(int st,int f)
    {
    	rt[st]=T.insert(rt[f],1,cnt,a[st]);
    	for(re i=head[st];i;i=next[i])
    	{
    		int p=to[i];
    		if(p==f)
    			continue;
    		dfs3(p,st);
    	}
    }
    signed main()
    {
    	n=read();
    	q=read();
    	type=read();
    	for(re i=1;i<=n;i++)
    	{
    		a[i]=read();
    		lsh[++cnt]=a[i];
    	}
    	for(re i=1,u2,v2;i<n;i++)
    	{
    		u2=read();
    		v2=read();
    		add(u2,v2);
    		add(v2,u2);
    	}
    	dfs(1,0);
    	dfs2(1,1);
    	if(q==0)
    		return 0;
    	for(re i=1;i<=q;i++)
    	{
    		cun_r[i]=read();
    		lsh[++cnt]=cun_r[i];
    		cun_k[i]=read();
    		for(re j=1;j<=cun_k[i];j++)
    			v[i].push_back(read());
    	}
    	sort(lsh+1,lsh+cnt+1);
    	cnt=unique(lsh+1,lsh+cnt+1)-lsh-1;
    	for(re i=1;i<=n;i++)
    		a[i]=lower_bound(lsh+1,lsh+cnt+1,a[i])-lsh;
    	for(re i=1;i<=q;i++)
    		cun_r[i]=lower_bound(lsh+1,lsh+cnt+1,cun_r[i])-lsh;
    	dfs3(1,0);
    	for(re i=1;i<=q;i++)
    	{
    		int lca,rk;
    		v[i][0]=(v[i][0]-1+ans*type)%n+1;
    		lca=v[i][0];
    		for(re j=1;j<v[i].size();j++)
    		{
    			v[i][j]=(v[i][j]-1+ans*type)%n+1;
    			lca=T.gett(lca,v[i][j]);
    		}
    		lca=fa[lca];
    		ans=INF;
    		for(re j=0;j<v[i].size();j++)
    		{
    			rk=T.query_rank(rt[lca],rt[v[i][j]],1,cnt,cun_r[i]);
    			if(rk>=(use[rt[v[i][j]]].sum-use[rt[lca]].sum))	
    			ans=min(ans,abs(lsh[T.query(rt[lca],rt[v[i][j]],1,cnt,rk)]-lsh[cun_r[i]]);
    			else
    			ans=min(ans,abs(lsh[T.query(rt[lca],rt[v[i][j]],1,cnt,rk+1)]-lsh[cun_r[i];
    			if(rk-1<=1)
    			ans=min(ans,abs(lsh[T.query(rt[lca],rt[v[i][j]],1,cnt,1)]-lsh[cun_r[i]]));
    			else	
    			ans=min(ans,abs(lsh[T.query(rt[lca],rt[v[i][j]],1,cnt,rk-1)]-lsh[cun_r[i];
    			if(rk>=1&&rk<=use[rt[v[i][j]]].sum-use[rt[lca]].sum)
    			ans=min(ans,abs(lsh[T.query(rt[lca],rt[v[i][j]],1,cnt,rk)]-lsh[cun_r[i]]);
    		}
    		printf("%lld\n",ans);
    	}
    	
    	return 0;
    }
    

    T3 f

    补坑:
    树状数组求逆序对,我们对于一个序列倒序枚举,显然,根据逆序对的定义,我们查询的小于当前数的权值的前缀和即为当前点的逆序对个数,注意,我们的树状数组建立在总序列的值域的基础上

        for(re i=1;i<=n;i++)
    	{
    		a[i]=read()+1;
    		maxx=max(a[i],maxx);	
    	}
    	for(re i=n;i;i--)
    	{
    		ans+=ask(a[i]-1);
    		add(a[i],1);
    	}
    	cout<<ans<<endl;
    
  • 相关阅读:
    并发编程之多线程理论
    僵尸进程和孤儿进程
    并发编程之多进程
    并发编程之多进程理论
    操作系统介绍
    面向对象和网络编程练习题
    网络编程——socket编程
    面向对象练习题
    面向对象软件开发实战
    异常处理
  • 原文地址:https://www.cnblogs.com/WindZR/p/15043478.html
Copyright © 2011-2022 走看看