1. 程式人生 > 其它 >noip模擬測試22

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]的時候我們就不能進行查詢,具體實現見程式碼:

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;