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;
    
  • 相关阅读:
    几种常用的曲线
    0188. Best Time to Buy and Sell Stock IV (H)
    0074. Search a 2D Matrix (M)
    0189. Rotate Array (E)
    0148. Sort List (M)
    0859. Buddy Strings (E)
    0316. Remove Duplicate Letters (M)
    0452. Minimum Number of Arrows to Burst Balloons (M)
    0449. Serialize and Deserialize BST (M)
    0704. Binary Search (E)
  • 原文地址:https://www.cnblogs.com/WindZR/p/15043478.html
Copyright © 2011-2022 走看看