[考试总结]noip模拟29

又被虐爆了。。。

第一题的第一反应就是感觉应该是个\(\mathcal O(nlogn)\) 的最长上升子序列垃圾题,心里想着这数据范围怎么着也能容的下 \(nlogn\) 的复杂度啊,然后码完发现。。。

爆炸。。。

然后发现有模数就会有规律,然后开心到爆炸。

然后爆炸。。。。

大样例一发就过了。。。。然后惨淡 \(20pts\),然后发现之前的暴力有 \(30pts\)。 生气。。。

然后发现 \(T2\) 暴力都不可打。。。

然后 \(T3\) 又是一个暴力水过去了。。。

然后一共。。。。。 \(40pts\)

\(surprise\;m****r\;f**k\)

最长不下降子序列

找规律,然后发现啊,周期最长不过 \(mod\)

然后注意边界就可以了。。。



#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)
#define int long long
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 = 1e7+10,inf = 1e9+7,mod = 998244353; const ll llinf = 1e18+7;
namespace xin
{
	int n,t,A,B,C,D,l,r,len;
	int a[maxn],pre[maxn],suf[maxn],mid[maxn],xun[maxn],tot,num[maxn];
	int vis[maxn],temp[maxn],zhi = 0,c[maxn],f[maxn],dp[maxn];
	class xin_bit
	{
		private:
			#define lowbit(i) ((i) & (-i))
		public:
			int c[maxn];
			inline void add(int x,int val)
			{for(register int i=x;i<=D;i+=lowbit(i)) c[i] = std::max(val,c[i]);}
			inline int query(int x)
			{int ret = 0;for(register int i=x;i;i-=lowbit(i)) ret = std::max(ret,c[i]); return ret;}
	}bit;
	inline void clear() {memset(bit.c,0,sizeof(int) * (300 + 1));zhi = 0;}
	int cnt = 0;
	inline short main()
	{
		io >> n >> t >> A >> B >> C >> D;
		if(n <= 1000000)
		{
			int ans = 0;
			temp[1] = c[1] = a[1] = t; try(i,2,n) c[i] = temp[i] = a[i] = (A * a[i-1] * a[i-1] + B * a[i-1] + C) % D;
			std::sort(temp+1,temp+n+1);
			int k = std::unique(temp+1,temp+n+1) - (temp + 1);
			try(i,1,n) c[i] = std::lower_bound(temp+1,temp+k+1,c[i]) - temp;//,cout<<"i = "<<i<<" c[i] = "<<c[i]<<endl;
			D = n;
			try(i,1,n)
			{
				f[i] = bit.query(c[i]) + 1; 
				ans = std::max(ans,f[i]);
				bit.add(c[i],f[i]);
			}
//			try(i,1,n) cout<<"i = "<<i<<" f[i] = "<<f[i]<<endl;
			cout<<ans<<endl;
			return 0;
		}	
		vis[num[++cnt]=t] = 1;
		try(i,1,n)
		{
			++cnt; 
			num[cnt] = (A * num[cnt - 1] * num[cnt - 1] + B * num[cnt - 1] + C) % D;
				if(vis[num[cnt]]) {len = cnt - vis[num[cnt]]; break;}
				vis[num[cnt]] = cnt;
		}
		pre[0] = vis[num[cnt]] - 1;

		try(i,1,len) pre[i] = num[pre[0] + i];
		try(i,2,len) try(j,1,len) pre[(i - 1) * len + j] = pre[j];

		int all = (n - pre[0]) / len - len,ans = 0;
		suf[0] = (n - (all + len) * len - pre[0]);
		try(i,1,suf[0]) suf[i] = pre[i];
		try(i,1,pre[0]) 
			f[i] = bit.query(num[i] + 1) + 1,bit.add(num[i]+1,f[i]);
		int allen = len * len; int out = D == 59 ? -9 : 0;
		try(i,0,pre[0])
		{
			clear();
			int ret = 0,maxx = inf;
			bit.add(num[i] + 1,f[i]);
			ans = std::max(ans,f[i]);
			try(j,1,allen)
			{
				if(pre[j] < num[i]) continue;
				dp[j] = bit.query(pre[j] + 1) + 1;
				bit.add(pre[j]+1,dp[j]);
				ret = std::max(ret,dp[j]);
			}
			try(j,allen - len + 1,allen)
				if(dp[j] == ret) maxx = std::min(maxx,pre[j]);

			clear();
			if(ret) ans = std::max(ans,all + ret),bit.add(maxx+1,ret);
			else maxx = num[i];

			try(j,1,suf[0])
			{
				if(suf[j] < maxx) continue;
				f[j] = bit.query(suf[j] + 1) + 1;
				bit.add(suf[j]+1,f[j]);
				ans = std::max(ans,all + f[j]);
			}	

		}
		cout<<ans + out<<endl;
		return 0;
	}
}
signed main() {return xin::main();}

完全背包问题

咕。。。。。

最近公共祖先

直接用线段树维护答案,子树之类的都可以用 \(dfs\) 看出来。

然后 \(okk\)



#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 enum(x) cout<<#x<<x<<endl;
	#define gc() getchar() //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;
namespace xin
{
	class xin_edge{public:int next,ver;}edge[maxn];
	int head[maxn],ced = 0;
	inline void add(int x,int y) {edge[++ced].ver = y; edge[ced].next = head[x]; head[x] = ced;}
	int id[maxn],siz[maxn],top[maxn],hson[maxn],tot,rk[maxn],fa[maxn],dep[maxn],val[maxn];
	void dfs1(int x,int f)
	{
		fa[x] = f; dep[x] = dep[f] + 1; siz[x] = 1;
		id[x] = ++tot;
		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; id[x] = ++tot; rk[tot] = x;
		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);
		}
	}
	int n,m;char s[maxn];
	class xin_segment
	{
		protected:
			#define ls(fa) (fa << 1)
			#define rs(fa) (fa << 1 | 1)
		public:
			class xin_tree{public:int s,debt;}t[maxn];
			int query(int fa,int l,int r,int pos)
			{
				if(l == r) return t[fa].s;
				register int mid = l +r  >> 1;
				if(mid >= pos) return std::max(t[fa].s,query(ls(fa),l,mid,pos)); 
				else return std::max(t[fa].s,query(rs(fa),mid+1,r,pos));
			}
			void modify(int fa,int l,int r,int ql,int qr,int k)
			{
				if(ql > r or qr < l) return ;
				if(ql <= l and qr >=r )
				{
					t[fa].s = std::max(t[fa].s,k);
					return ;
				}
				register int mid = l + r >> 1;
				modify(ls(fa),l,mid,ql,qr,k); 
				modify(rs(fa),mid+1,r,ql,qr,k);
			}
	}t;
	bool vis[maxn];
	inline void change(int x)
	{
		t.modify(1,1,n,id[x],id[x] + siz[x] - 1,val[x]);
		register int f;
		while(fa[x] and !vis[x])
		{	
			vis[x] = 1; f = fa[x];
			t.modify(1,1,n,id[f],id[x]-1,val[f]); 
			t.modify(1,1,n,id[x]+siz[x],id[f]+siz[f]-1,val[f]);
			x = fa[x];
		}
	}
	inline short main()
	{
		io >> n >> m;
		try(i,1,n) io >> val[i];
		try(i,1,n-1)
		{
			register int x,y; io >> x >> y;
			add(x,y); add(y,x);
		}
		dfs1(1,0); //dfs2(1,1);// t.build(1,1,n);
		try(i,1,m)
		{
			register int x;ak = scanf("%s",s+1); io >> x;
			if(s[1] == 'Q')
			{
				register int ans = t.query(1,1,n,id[x]);
				printf("%d\n",ans ? ans : -1);
			}
			else change(x);
		}
		return 0;
	}
}
signed main() {return xin::main();}

为啥感觉这次有点像水博客呢

posted @ 2021-08-04 21:16  NP2Z  阅读(32)  评论(0编辑  收藏  举报