ICode9

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

[考试总结]noip模拟38

2021-08-14 06:31:30  阅读:173  来源: 互联网

标签:std 38 noip int register try ch lisan 模拟


。。。。

\(boom\)

不知道怎么的 \(T1\) 上来我就给跳过了,然后就开始先干\(T3\),感觉并不是很简单,但是也不是能说是很难。

然后我就突然想到了一种可以过掉一半数据的 \(dp\),之后居然一下子就成功了。

大样例一测,过了?!

之后感觉还行,然后回头管 \(T1\),但是却没有发现那个极其显然的双指针,然后我人无,还在 \(l\) 和 \(r\) 输出之前就特判 \(l\),\(r\),然后惨烈。。。。

\(T2\) 本以为有一些部分分数,然而一分也没有。。。。。

a

我们如果固定左上的那一个端点,就会发现这个对于接下来的 \(n-i+1\) 行,它的合法范围其实都是有关联的。

如果我们使用莫队的思想 \((two\;pointers)\),就会每一行均摊一个 \(m\),之后就是 \(\mathcal O(n^2m)\)



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define asm(i,x) for(register signed i=head[x];i;i=edge[i].next)
namespace xin_io
{
	#define debug cout<<"debug"<<endl
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	#define scanf ak = scanf
	int ak;
}
#define int long long
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7;
namespace xin
{
	#define calc(x1,y1,x2,y2) (he[x2][y2] - he[x2][y1-1] - he[x1-1][y2] + he[x1-1][y1-1])
	int n,m;
	int l,r,ans = 0;
	char s[maxn];
	int he[31][maxn/10];
	int los[maxn],ros[maxn];
	inline short main()
	{
		scanf("%lld%lld",&n,&m);
		try(i,1,n)
		{
			scanf("%s",s+1);
			try(j,1,m)
			{
				he[i][j] = he[i-1][j] + he[i][j-1] - he[i-1][j-1] + (s[j] == '1');//,cout<<he[i][j]<<' ';
		//		if(s[j] == '1') sp1 = 0;
			}
		}
		scanf("%lld%lld",&l,&r);
		if(l == 0 and r == n * m)
		{
			cout<<((n + 1) * n / 2) * ((m + 1) * m/ 2)<<endl;
			return 0;
		}
		try(i,0,n-1) 
		{
			memset(los,0,sizeof(int) * (n + 1));
			memset(ros,0,sizeof(int) * (n + 1));
			try(j,0,m-1)
			{	
				try(x,i+1,n)
				{
					try(y,los[x],m)
					{
						if(he[x][y] - he[i][y] - he[x][j] + he[i][j] >= l)
							{los[x] = y; break;}
						if(y == m) los[x] = m + 1;
					}
					try(y,ros[x]+1,m)
					{
						if(he[x][y] - he[i][y] - he[x][j] + he[i][j] > r)
							{ros[x] = y - 1; break;}
						if(y == m) ros[x] = m;
					}
					ans += ros[x] - los[x] + 1;
				}
			}
		}
		cout<<ans<<endl;
		return 0;
	}
}
signed main() {return xin::main();}

b

题解写的多好


#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define asm(i,x) for(register signed i=head[x];i;i=edge[i].next)
namespace xin_io
{
	#define debug cout<<"debug"<<endl
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
	class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &x)
	{
		register type s = 0; register int f = 1; register char ch = gc();
		while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return x = s * f,*this;
	}}io;
}
#define int long long
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7,mod = inf; const ll llinf = 1e18+7;
namespace xin
{
	int cnt[21][maxn/10],n,m,ans = 0,ton[21][maxn/10],s[maxn],maxx = -inf;
	inline short main()
	{
		io >> n >> m;
		try(i,1,n)try(j,1,m)
		{
			register int x; io >> x;
			ton[i][x]++; maxx = std::max(maxx,x);
		}
		try(i,1,n) try(j,1,maxx) for(register int k=1;k*j<=maxx;++k)
			cnt[i][j] += ton[i][j * k];	
		throw(j,maxx,1)
		{
			s[j] = 1; try(i,1,n) (s[j] *= (cnt[i][j] + 1) % mod) %= mod; s[j] --;
			if(!s[j]) continue;
			for(register int k=2;k * j <=maxx;++k) s[j] = (s[j] - s[k*j] + mod) % mod;
			(ans += s[j] * j % mod) %= mod;
		}
		cout<<ans<<endl;
		return 0;
	}
}
signed main() {return xin::main();}

c

这个虽然没有想出正解点分治,但是也是暴力分数中最大的想法了。

就是我们对于每次询问,遍历整张图,找到 \(x\) 到 \(y\) 经过的点的路径。

之后因为每两个点之间的边不止一条,而我们又要找到最大的价值,发现贪心不可,便开始 \(dp\)

我们考虑 \(f_{i,j}\) 为处理到 \(i\) 点,然后并且选择了这个点的颜色为 \(j\)

转移显然:

\[f_{i,j} = max_{k \ne }(f_{i-1,k})+1\\ f_{i,j} = max_{k = j}(f_{i-1,k}) \]

然后就是 \(\mathcal O(nq)\),只能过前 \(5\) 点。。。



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define asm(i,x) for(register signed i=head[x];i;i=edge[i].next)
namespace xin_io
{
	#define debug cout<<"debug"<<endl
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
	class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &x)
	{
		register type s = 0; register int f = 1; register char ch = gc();
		while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return x = s * f,*this;
	}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7; const ll llinf = 1e18+7;
namespace xin
{
	class xin_edge{public:int next,ver,w;}edge[maxn];
	int head[maxn],ced = 0;
	inline void add(int x,int y,int z) {edge[++ced].ver = y;edge[ced].w = z; edge[ced].next = head[x]; head[x] = ced;}
	int n,m,qnum;
	bool vis[maxn];
	int pre[maxn];
	void dfs(int x,int goal)
	{
		vis[x] = 1;
		if(x == goal) return;
		asm(i,x)
		{
			register int y = edge[i].ver;
			if(!vis[y])
			{
				pre[y] = x;
				dfs(y,goal);
			}
		}
	}
	void outp(int x)
	{
		if(!x) return;
		cout<<x<<' ';
		outp(pre[x]);
	}
	std::vector<int>vec[501][501];
	int f[501][10001];
	int maxx = 0,ans = -inf;
	void dp(int x,int i)
	{
		if(!x)
		{
			return ;
		}
		for(auto j : vec[x][pre[x]])
		{
			try(k,1,maxx)
				if(k xor j)
					f[i][j] = std::max(f[i-1][k] + 1,f[i][j]),ans = std::max(ans,f[i][j]);
				else 
					f[i][j] = std::max(f[i-1][k],f[i][j]),ans = std::max(ans,f[i][j]);
		}
		dp(pre[x],i+1);
	}
	class xin_data
	{
		public:
			int x,y,z;
	}d[maxn];
	int lisan[maxn],cnt;
	bool sp1 = 1;
	int top[maxn],hson[maxn],dep[maxn],fa[maxn],siz[maxn];
	void dfs1(int x,int f)
	{
		siz[x] = 1; dep[x] = dep[f] + 1; fa[x] =f;
		asm(i,x)
		{
			register int y = edge[i].ver;
			if(y == f) continue;
			dfs1(y,x);
			siz[x] += siz[y];
			if(siz[y] > siz[hson[x]]) hson[x] = y;
		}
	}
	void dfs2(int x,int t)
	{
		top[x] = t; 
		if(hson[x]) dfs2(hson[x],t);
		asm(i,x)
		{
			register int y = edge[i].ver;
			if(y == hson[x] or y == fa[x]) continue;
			dfs2(y,y);
		}
	}
	inline int lca(int x,int y)
	{
		while(top[x] xor top[y])
		{
			if(dep[top[x]] < dep[top[y]]) std::swap(x,y);
			x = fa[top[x]];
		}
		if(dep[x] > dep[y]) return y; return x;
	}
	inline short main()
	{
		io >> n >> m;
		try(i,1,m)
		{
			io >> d[i].x >> d[i].y >> d[i].z;
			lisan[++cnt] = d[i].z;
		}
		io >> qnum; if(!qnum) {return 0;}
		std::sort(lisan+1,lisan+cnt+1);
		maxx = std::unique(lisan+1,lisan+cnt+1) - (lisan + 1);
		try(i,1,m)
		{
			d[i].z = std::lower_bound(lisan+1,lisan+maxx+1,d[i].z) - lisan;
			add(d[i].x,d[i].y,d[i].z); add(d[i].y,d[i].x,d[i].z);
			if(n <= 500 and vec[d[i].x][d[i].y].size()) sp1 = 0;
			if(n <= 500 )vec[d[i].x][d[i].y].push_back(d[i].z),vec[d[i].y][d[i].x].push_back(d[i].z);
		}
		try(que,1,qnum)
		{
			register int x,y; io >> x >> y;
			memset(vis,0,sizeof(bool) * (n + 1));
			memset(pre,0,sizeof(int ) * (n + 1));
			try(i,1,n) try(j,1,maxx) f[i][j] = 0;
			ans = 0;
			dfs(x,y);
//			outp(y);cout<<endl;
			dp(y,1);
			cout<<ans<<endl;
		}
		return 0;
	}
}
signed main() {return xin::main();}

标签:std,38,noip,int,register,try,ch,lisan,模拟
来源: https://www.cnblogs.com/NP2Z/p/15139761.html

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

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

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

ICode9版权所有