ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

(联考)noip83

2021-10-27 06:31:07  阅读:144  来源: 互联网

标签:ch int noip83 re freopen delta BIT 联考


T1

考场拿 \(O(n)\) 拍自己 \(O(n\log n)\) 的,交的后者,于是死了
,只有60pts,本地1.3s的,accoder上跑不出来....

\(O(n)\) 的还要大力卡常...

本地0.7s才能过就离谱。

直接搜即可。

每个点只会被更新一次,均摊 \(O(n)\) 。

T2

部分分很多,80pts。

25pts:暴力乱写。

25+20pts:直接sort完二分。

25+20+20pts:monkey说拿指针乱扫。

25+20+20+15pts:用树状数组维护一下到根节点有多少比当前点小的,dfs一遍即可。

100pts:

题目实际上就是在求在以 \(rt\) 为根时,每个点的子树内有多少个点权值比它小的点的个数的总和。

用task4的做法,先求出以1为根时的答案。

然后就可以用换根dp求出每个点 \(u\) 的答案。

具体转移:

从点 \(u\) 转移到点 \(v,v\in son_{u}\) 时,通过画图可以发现,以1为根时点 \(v\) 的子树内的点,都少经过一个点 \(u\) ,整棵树除了以 \(v\) 为根节点的子树的那部分,都要多经过一个点 \(v\) 。

于是可以设 \(g_{v,1}\) 表示以 \(v\) 为根的子树有多少点的权值比 \(w_{v}\) 小, \(g_{v,0}\) 表示以 \(v\) 为根的子树中多少比 \(u,u=fa_{v}\) 的权值小的点, \(f_{v}\) 表示以 \(v\) 为根时的答案。

转移则有: \(f_{v}=f_{u}-g_{v,0}+query(w_{v}-1)-g_{v,1}\)

\(g\) 数组同样可以通过dfs+BIT得到,差分即可。

\(query\) 为BIT的查询函数,查询有多少比当前点权值小的点。

求 \(g\) 时的dfs已经更新了BIT,所以转移时的差分直接用BIT即可。

Code
#include<cstdio>
#include<cctype>
#include<algorithm>
#define re register
const int MAX = 1e6+7;
#define scanf oma=scanf
#define freopen file=freopen
using std::sort;
using std::unique;
using std::lower_bound;
int oma;
FILE* file;
namespace some
{
	struct stream
	{
		template<typename type>inline stream &operator >>(type &s)
		{
			bool w=0; s=0; char ch=getchar();
			while(!isdigit(ch)){ w|=ch=='-'; ch=getchar(); }
			while(isdigit(ch)){ s=(s<<1)+(s<<3)+(ch^48); ch=getchar(); }
			return s=w?-s:s,*this;
		}
	}cin;
	int n,q,w[MAX];
	int tmp[MAX],tot;
	#define debug(s) printf("%s\n",s)
}using namespace some;
namespace Binary_Index_Tree
{
	struct BIT
	{
		int val[MAX];
		#define lowbit(x) x&-x
		void modify(int x,int w)
		{ for(re int i=x; i<=n+1; i+=lowbit(i)) { val[i] += w; } }
		int query(int x,int res = 0)
		{ for(re int i=x; i; i-=lowbit(i)) { res += val[i]; } return res; }
	}bit;
}using namespace Binary_Index_Tree;
namespace Graph
{
	struct graph
	{ int next,to; }edge[MAX<<1];
	int cnt=1,head[MAX];
	auto add = [](int u,int v) { edge[++cnt] = (graph){head[u],v},head[u] = cnt; };
	int g[MAX][2]; // 0 fa 1 self
	long long f[MAX];
	void dfs_rt(int u,int fa)
	{
		bit.modify(w[u],1);
		for(re int i=head[u],v; i; i=edge[i].next)
		{
			v = edge[i].to;
			if(v!=fa)
			{ f[1] += bit.query(n+1)-bit.query(w[v]); dfs_rt(v,u); }
		}
		bit.modify(w[u],-1);
	}
	void dfs_pre(int u,int fa)
	{
		g[u][1] -= bit.query(w[u]-1);
		if(u!=1) { g[u][0] -= bit.query(w[fa]-1); }
		bit.modify(w[u],1);
		for(re int i=head[u],v; i; i=edge[i].next)
		{
			v = edge[i].to;
			if(v!=fa)
			{ dfs_pre(v,u); }
		}
		g[u][1] += bit.query(w[u]-1);
		if(u!=1) { g[u][0] += bit.query(w[fa]-1); }
	}
	void dfs_ex(int u,int fa)
	{
		for(re int i=head[u],v; i; i=edge[i].next)
		{
			v = edge[i].to;
			if(v!=fa)
			{ f[v] = f[u]-g[v][0]+bit.query(w[v]-1)-g[v][1]; dfs_ex(v,u); }
		}
	}
}using namespace Graph;
namespace right
{
	auto solve = []() -> void
	{
		for(re int i=1; i<=n; i++)
		{ tmp[i] = w[i]; }
		sort(tmp+1,tmp+1+n);
		//printf("%d\n",lower_bound(tmp+1,tmp+1+n,w[2])-tmp-1);
		tot = unique(tmp+1,tmp+1+n)-tmp-1;
		for(re int i=1; i<=n; i++)
		{ w[i] = lower_bound(tmp+1,tmp+1+tot,w[i])-tmp; }
		dfs_rt(1,0),dfs_pre(1,0),dfs_ex(1,0);
		for(re int i=1,u; i<=q; i++)
		{ cin >> u; printf("%lld\n",f[u]); }
	};
};
namespace OMA
{
	auto main = []() -> signed
	{
		//freopen("node.in","r",stdin); freopen("my.out","w",stdout);
		freopen("tears.in","r",stdin); freopen("tears.out","w",stdout);
		cin >> n >> q;
		for(re int i=1; i<=n; i++)
		{ cin >> w[i]; }
		for(re int i=1,u,v; i<n; i++)
		{ cin >> u >> v; add(u,v),add(v,u); }
		right::solve();
		return 0;
	};
}
signed main()
{ return OMA::main(); }

T3

经典dp+线段树维护矩阵。

T4

求个差分数组 \(delta\),如果 \(delta>0\) 则压入队列,反之,如果要求最大值,则用队尾元素来消当前 \(delta\) ,把距离远的留给后边的。最小值则相反,用队首元素来消,距离近的留给后面的。

差分数组要算到 \(n+1\) ,因为操作区间实际上是 \([l,r-1]\) 。

同时不难发现,最短时间则为 \(\sum_{i=1}^{n}\max(delta_{i},0)\) 。

因为 \(d_{i}\ge0\) ,所以当前小于0的 \(delta_{i}\) 一定能被队列里的元素消成0。

用deque实现即可。

反思总结

csp后第一次模拟,还是联考,考的并不太行,T1没算复杂度,高估了accoders的评测机,T2沉迷于部分分,还打挂了,正解不算难,却往换根dp上想,T4的部分分同样写挂。

很多地方做的还是不太行,T1没细想,T3暴力浪费了时间,考试过程中也会走私。

noip也不远了,只能说继续加油吧。

标签:ch,int,noip83,re,freopen,delta,BIT,联考
来源: https://www.cnblogs.com/-OMA-/p/15468769.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有