ICode9

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

[考试总结]noip模拟34

2021-08-10 06:31:06  阅读:115  来源: 互联网

标签:ch noip int register mid 34 try fa 模拟


实际上简单的题目并不能被题目所吓到,仔细分析实际上难度并不是很高。

如果存在显然的部分分数,其实特盘一下也比较好,有可能你的程序就卡在这个地方。。

这次暴力打的不是很挂,\(T1\) 也还是差一个 \(nth\)_\(element\) ,二分答案的思路显然,但是要有两个 \(log_2\)

\(T2\) 没有进行仔细的分析,实际上手动推导发现可以推导成为一个形式,并且与深度的奇偶性有关。

\(T3\) 这个属实大神题,需要使用常熟优秀的树状数组。

Merchant

我们首先进行二分答案,二分时间,然后进行统计 \(check\),但是发现如果在 \(check\)中使用 \(sort\),就会 \(TLE\) 成 \(78pts\) ,因为这时的复杂度是 \(nlog^2\) 。

然后我们其实可以发现,我们并不需要让他有序,我们只需要将前 \(m\) 大小的提到一边。

这时 \(nth_element\) 的作用就体现出来了,之后我们就可以 \(\mathcal O(n)\) 排除顺序,之后加和比较。



#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 enum(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 = 2e6+10,inf = 1e9+7,mod = 998244353; const ll llinf = 1e18+7;
namespace xin
{
	class xin_data
	{
		public:
			int k,b;
			xin_data(){}
			xin_data(int k,int b):k(k),b(b){}
			inline int val(int t) {return k * t + b;}
	}d[maxn];
	int n,m,s,temp;
	int a[maxn];
	inline bool comp(int x,int y) {return x > y;}
	inline bool check(int x)
	{
		try(i,1,n) a[i] = d[i].val(x);
		std::nth_element(a+1,a+(n-m),a+n+1);
		s = temp;
		throw(i,n,n-m+1)
		{
			if(a[i] < 0) continue;
			s -= a[i];
			if(s <= 0) return true;
		}
		return false;
	}
	inline short main()
	{
		io >> n >> m >> s; temp = s;
		try(i,1,n)	io >> d[i].k >> d[i].b;
		register int l = 0,r = inf,mid;
		if(check(0)) {cout<<0<<endl; return 0;}
		while(l != r - 1 and l < r)
		{
			mid = l + r >> 1;
			if(check(mid)) r = mid;
			else l = mid;
		}
		if(check(l)) cout<<l<<endl;
		else if(check(mid)) cout<<mid<<endl;
		else cout<<r<<endl;
//		cout<<sizeof(a) / (1 << 20)<<" MB"<<endl;
		return 0;	
	}
}
signed main() {return xin::main();}

Equation

我们进行推导,发现每一个式子都可以推成

\[x_1=k+x_u \]

或者

\[x_1=k-x_u \]

这个符号取决与深度的奇偶性。

然后我们强制使树的边权正负交错,也就是 \(sum_y=w_y-sum_x\)

然后对于 \(2\) 操作,在线段树上维护即可。



#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 enum(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,mod = 998244353; const ll llinf = 1e18+7;
#define int long long
namespace xin
{
	class xin_edge{public:int w,next,ver;}edge[maxn];
	int head[maxn],zhi = 0;
	inline void add(int x,int y,int z) {edge[++zhi].ver = y; edge[zhi].w = z; edge[zhi].next = head[x]; head[x] = zhi;}
	class xin_seg
	{
		private:
			#define ls(fa) (fa << 1)
			#define rs(fa) (fa << 1 | 1)
			inline void up(int fa) {t[fa].s = t[ls(fa)].s + t[rs(fa)].s;}
			inline void down(int fa,int l,int r)
			{
				if(!t[fa].debt) return ;
				register int mid = l + r >> 1;
				t[ls(fa)].s += t[fa].debt * (mid - l + 1); t[rs(fa)].s += t[fa].debt * (r - mid);
				t[ls(fa)].debt += t[fa].debt; t[rs(fa)].debt += t[fa].debt;
				t[fa].debt = 0;
			}
		public:
			class xin_tree{public:int s,debt;}t[maxn * 4];
			void update(int fa,int l,int r,int ql,int qr,int val)
			{
				if(ql <= l and qr >= r) return t[fa].s += (r - l + 1) * val,t[fa].debt += val,void();
				register int mid = l + r >> 1;
				down(fa,l,r);
				if(ql <= mid) update(ls(fa),l,mid,ql,qr,val);
				if(qr >  mid) update(rs(fa),mid+1,r,ql,qr,val);
				up(fa);
			}
			int query(int fa,int l,int r,int pos)
			{
				if(l == r) return t[fa].s;
				register int mid = l + r >> 1,ret = 0; down(fa,l,r);
				if(pos <= mid) ret += query(ls(fa),l,mid,pos); 
				else ret += query(rs(fa),mid+1,r,pos);
				return ret;
			}
	}t;


	int n,qnum,fa[maxn];
	int in[maxn],out[maxn],tot = 0,d[maxn],sum[maxn],w[maxn];
	void xt(int x)
	{
		in[x] = ++tot; d[x] = d[fa[x]] + 1;
		asm(i,x)
		{
			register int y = edge[i].ver;
			sum[y] = w[y] - sum[x];
			xt(y);
		}
		out[x] = tot;
	}
	inline short main()
	{
		io >> n >> qnum;
		try(i,2,n)
		{
			io >> fa[i] >> w[i];
			add(fa[i],i,w[i]);
		}
		xt(1);
		try(i,1,qnum)
		{
			register int op; io >> op;
			if(op & 1)
			{
				register int x,y,z; io >> x >> y >> z;
				register int p1 = t.query(1,1,n,in[x]),p2 = t.query(1,1,n,in[y]);
				if(!(d[x] & 1)) p1 = -p1; if(!(d[y] & 1)) p2 = -p2;
				register int ret1 = sum[x] + p1,ret2 = sum[y] + p2;
				if((d[x] & 1) and (d[y] & 1)) 
				{
					if((z - ret1 - ret2) & 1) puts("none");
					else printf("%lld\n",(z - ret1 - ret2) >> 1);
				}
				else if(!(d[x] & 1) and !(d[y] & 1))
				{
					if((ret1 + ret2 - z) & 1) puts("none");
					else printf("%lld\n",(ret1 + ret2 - z) >> 1);
				}
				else
				{
					if(ret1 + ret2 == z) puts("inf");
					else puts("none");
				}
			}
			else
			{
				register int x,z; io >> x >> z;
				register int p = z - w[x];
				w[x] = z;
				if(!(d[x] & 1)) p = -p;
				t.update(1,1,n,in[x],out[x],p);
			}
		}
		return 0;
	}
}
signed main() {return xin::main();}

Rectangle

首先第一思路就是拿四个线卡来卡去。

然后就是 \(n^4\)

可以拿二十多分。。

正解实际上是先拿两条线。

之后发现答案贡献与两条线之间的 \(y\) 有关,所以用树状数组来维护 \(\sum y\)

#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 enum(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 = 2500+10,inf = 1e9+7,mod = 1e9+7; const ll llinf = 1e18+7;
namespace xin
{
	#define int long long
	int n;
	class xin_bit
	{
		private:
			#define lowbit(x) (x & -x)
		public:
			int c[2][maxn][maxn];
			inline void plus(int id,int k,int x,int val)
			{
				for(int i=x;i<=2500;i+=lowbit(i))
					c[id][k][i] += val;
			}
			inline int query(int id,int k,int x)
			{
				register int ret = 0;
				for(int i=x;i;i-=lowbit(i)) ret += c[id][k][i];
				return ret;
			}
	}bit;
	int a[maxn][maxn],ans;
	bool vis[maxn][maxn];
	inline short main()
	{
		io >> n;
		try(i,1,n)
		{
			register int x,y; io >> x >> y;
			a[x][++a[x][0]] = y; 
		}
		try(i,1,2500)
		{
			std::sort(a[i]+1,a[i]+a[i][0]+1);
			a[i][a[i][0]+1] = 2501;
		}
		try(i,1,2500)
		{
			if(!a[i][0]) continue;
			try(j,1,a[i][0])
			if(!vis[i][a[i][j]])
			{
				vis[i][a[i][j]] = 1;
				bit.plus(1,i,a[i][j],1);
				bit.plus(0,i,a[i][j],a[i][j]);
			}
			throw(j,i-1,1)
			{
				if(!a[j][0]) continue;
				register int l1 = 1,l2 = 1;
				try(k,1,a[j][0])
					if(!vis[i][a[j][k]])
					{
						vis[i][a[j][k]] = 1;
						bit.plus(1,i,a[j][k],1);
						bit.plus(0,i,a[j][k],a[j][k]);
					}
				register int temp = std::max(a[i][1],a[j][1]);
				while(a[i][l1+1] <= temp) l1 ++; while(a[j][l2+1]<=temp) l2 ++;
				while(l1 <= a[i][0] and l2 <= a[j][0])
				{
					register int zhuan = std::min(a[i][l1+1],a[j][l2+1]);
					int ret1 = (bit.query(0,i,zhuan-1)-bit.query(0,i,temp-1));
					int ret2 = (bit.query(1,i,zhuan-1)-bit.query(1,i,temp-1));
					//enum(ret1); enum(ret2);
					ans=(ans+(i-j)*(ret1*bit.query(1,i,std::min(a[i][l1],a[j][l2]))-(ret2*bit.query(0,i,std::min(a[i][l1],a[j][l2])))))%mod;
					temp = zhuan;
					if(a[i][l1+1] <= temp) l1 ++; if(a[j][l2+1] <= temp) l2 ++;
				}
			}
		}
		cout<<ans<<endl;
		return 0;
	}
}
signed main() {return xin::main();}

标签:ch,noip,int,register,mid,34,try,fa,模拟
来源: https://www.cnblogs.com/NP2Z/p/15121914.html

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

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

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

ICode9版权所有