1. 程式人生 > 其它 >[考試總結]noip模擬27

[考試總結]noip模擬27

這個牛半仙可真的是人生贏家

這波中二的名字又是讓我心頭一震,然後有發現沒有 \(PDF\) 和大樣例。

沒有大樣例就意味著不能打掛一處。

然而這是讓我最頭疼的事情。。。

\(100\) 多行的程式碼一般對我來說也就是不到 \(5\) 分鐘就能打完,然後開始 \(50min\) 除錯。。。

有億點虧。。。

其實這樣的聯賽模擬題目使勁想一想還是可以想出正解的,然而腦袋裡不知道為什麼總是想要去打一個暴力。。。

確實該改一改這個毛病。

牛半仙的妹子圖

一開始看這個題目的時候就覺得這個出題人真的是中二至極。

這就是我打掛這個題目的理由

這個題目實際上很像奶牛跨欄那個題目,就是要求到達一個點路徑上的最小值的最大。

然而當時所有人似乎用的都是 \(floyed\) 高階演算法。。。

然後這個題目就不知道用 \(dij\) 咋搞。。。

其實也差不多,我想的是可以把所有邊壓進 ¥priority_queue$ 當中,這樣的話也能維護這個。

然而因為不是很經常使用 \(dijkstra\)\(priority_queue\),所以。。。

我壓根不知道該 反著過載

所以我是這麼寫的。。。

class xin_data
{
	private:
		friend bool operator < (xin_data x,xin_data y)
		{return x.w < y.w;}
	public:
		int w,pos;
};

然後就 \(gg\) 了。

因為 \(w\leq600\) ,所以可以建立 權值陣列

然後就能跑了。



#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 int long long
namespace xin_io
{
	#define scanf nb = scanf
	#define debug cout<<"debug"<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<2,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf,output[100]; FILE *xinnb;int nb;typedef long long ll; typedef unsigned long long ull;
	void openfile() {xinnb = freopen("t.txt","r",stdin);} void outfile() {xinnb = freopen("o.txt","w",stdout);}
	inline int get()
	{
		register int s = 0,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 s * f;
	}
	template<typename type>inline void write(type x,char out)
	{
		if(!x) return putchar('0'),putchar(out),void(); if(x < 0) putchar('-'),x = -x;
		register int cnt = 0;while(x) output[++cnt] = x % 10,x /= 10; 
		throw(i,cnt,1) putchar(output[i] xor 48);return putchar(out),void();
	}
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7; static const ll llinf = 1e17+7;
namespace xin
{
	class xin_edge{public:int next,ver,w;}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_data
	{
		private:
			friend bool operator < (xin_data x,xin_data y)
			{return x.val > y.val;}
		public:
			int val,pos;
			xin_data(){}
			xin_data(int val,int pos):val(val),pos(pos){}
	};
	std::priority_queue<xin_data>q;
	int n,m,qnum,st,op,mod,c[maxn],dis[maxn];
	int ton[maxn],sum = 0;
	int he[maxn],base[maxn],cnt,num[maxn];
	bool vis[maxn];
	inline short main()
	{
	#ifndef ONLINE_JUDGE
		openfile();
	#endif
		n = get(); m = get(); qnum = get(); st = get(); op = get(); if(op) mod = get();
		try(i,1,n) c[i] = get();
		try(i,1,m)
		{
			register int x = get(),y = get(),z = get();
			add(x,y,z); add(y,x,z);
		}
		ton[c[st]]++; sum ++;
		for(register int i=head[st];i;i=edge[i].next) q.push(xin_data(edge[i].w,edge[i].ver));
		int maxx = 0; base[++cnt] = 1; num[cnt] = sum;
		while(!q.empty())
		{
			register int dis = q.top().val,now = q.top().pos;q.pop();
			if(vis[now])continue;
			vis[now] = 1; maxx = std::max(maxx,dis);
			ton[c[now]]++; if(ton[c[now]] == 1) {sum++; if(base[cnt] xor maxx) base[++cnt] = maxx; num[cnt] = sum;}
			for(register int i=head[now];i;i=edge[i].next) q.push(xin_data(edge[i].w,edge[i].ver));
		}
		base[++cnt] = inf;
		try(i,1,cnt) he[i] = he[i-1] + num[i - 1] * (base[i] - base[i-1]);
		int pre = 0;
		try(i,1,qnum)
		{
			register int l = get(),r = get();
			if(op) l = (l xor pre) % mod + 1,r = (r xor pre) % mod + 1;
			if(r < l) std::swap(l,r);
			register int lb = std::upper_bound(base+1,base+cnt+1,l) - base,rb = std::upper_bound(base+1,base+cnt+1,r) - base - 1;
			register int ans = he[rb] - he[lb];
			ans += (base[lb] - l) * num[lb - 1]; ans += (r - base[rb] + 1) * num[rb];
			write(pre = ans,'\n');
		}
		return 0;
	}
}
signed main(){return xin::main();}

牛半仙的妹子Tree

這個題目說實話我是真的沒有想到暴力直接可過的。

然後加強資料之後。。。還是能過。。。

其實就是記錄下來每一個 \(1\) 操作。

然後在每一個 \(3\) 操作的時候遍歷整個 \(1\) 操作的陣列。

然後而操作就是把那個陣列的指標清零就行了。

然而 \(lca\) 一定要 \(\mathcal O(1)\) 求,不然一定會 \(T\)



#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)
namespace xin_io
{
	#define scanf nb = scanf
	#define debug cout<<"debug"<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<2,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf,output[100]; FILE *xinnb;int nb;typedef long long ll; typedef unsigned long long ull;
	void openfile() {xinnb = freopen("t.txt","r",stdin);} void outfile() {xinnb = freopen("o.txt","w",stdout);}
	inline int get()
	{
		register int s = 0,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 s * f;
	}
	template<typename type>inline void write(type x,char out)
	{
		if(!x) return putchar('0'),putchar(out),void(); if(x < 0) putchar('-'),x = -x;
		register int cnt = 0;while(x) output[++cnt] = x % 10,x /= 10; 
		throw(i,cnt,1) putchar(output[i] xor 48);return putchar(out),void();
	}
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7; static const ll llinf = 1e17+7;
namespace xin
{
	class xin_edge{public:int next,ver;} edge[maxn];
	int head[maxn],cnt = 0;
	inline void add(int x,int y){edge[++cnt].ver = y; edge[cnt].next = head[x]; head[x] = cnt;}
	int dep[maxn],f[maxn][32],lg[maxn],fr[maxn],num;
	void dfs(int x,int fa)
	{
		dep[x]=dep[fa]+1;
		f[++num][0] = x;
		if(!fr[x])fr[x]=num;
		for(int i=head[x];i;i=edge[i].next)
		{
			int dd=edge[i].ver;
			if(dd==fa)continue;
			dfs(dd,x);
			f[++num][0]=x;
			if(!fr[x])fr[x]=num;
		}
	}
	void RMQ()
	{
		for(register int j=1;(1<<j)<=num;++j)
			for(register int i=1;i+(1<<j)-1<=num;++i)
				if(dep[f[i][j-1]]<dep[f[i+(1<<(j-1))][j-1]])f[i][j]=f[i][j-1];
				else f[i][j]=f[i+(1<<(j-1))][j-1];
		try(i,2,num) lg[i] = lg[i>>1] + 1;
	}

	int lca(int x,int y)
	{
		x = fr[x]; y = fr[y];
		if(x > y) x ^= y ^= x ^= y;
		int len=lg[y-x+1];
		return dep[f[x][len]]<dep[f[y-(1<<len)+1][len]]?f[x][len]:f[y-(1<<len)+1][len];
	}
	inline int distance(int x,int y){return dep[x] + dep[y] - 2 * dep[lca(x,y)];}
	int a[maxn],temp[maxn],zhi = 0;
	int n,m;
	bool cold[maxn];
	void kuosan()
	{
		try(i,1,zhi) temp[i] = a[i];
		int ms = zhi; zhi = 0;
		try(i,1,ms)
		{
			register int x = temp[i];
			for(register int i=head[x];i;i=edge[i].next)
			{
				register int y = edge[i].ver;
				if(!cold[y]) cold[y] = 1,a[++zhi] = y;
			}
		}
	}
	class xin_data
	{
		public:
			int tim,pos;
			xin_data(){}
			xin_data(int tim,int pos):tim(tim),pos(pos){}
	}d[maxn];
	bool sp1 = 1,sp2 = 1;
	inline short main()
	{
	#ifndef ONLINE_JUDGE
		openfile();
	#endif
		n = get(); m = get();
		try(i,1,n-1)
		{
			register int x = get(),y = get();
			add(x,y); add(y,x);
			if(x xor 1) sp1 = 0;
			if((x xor i) or (y xor (i + 1))) sp2 = 0;						
		}
		if(sp1)
		{
			int tim = 0,cnt = 0;
			try(i,1,m)
			{
				register int op = get(),x = get();
				if(cnt)
				{
					if(cold[1]) cnt = n;
					else cold[1] = 1;
				}
				if(op == 1)
				{
					cold[x] = 1;
					cnt++;
				}
				if(op == 2)
				{
					cnt = 0;
					memset(cold,0,sizeof(bool) * (n + 1));
				}
				if(op == 3)
				{
					if(cnt == n) printf("wrxcsd\n");
					else printf(cold[x] ? "wrxcsd\n" : "orzFsYo\n");	
				}
			}
			return 0;
		}	
		if(sp2)
		{
			try(i,1,m)
			{
				register int op = get(),x = get();
				kuosan();
				if(op == 1)
				{
					a[++zhi] = x;
					cold[x] = true;
				}
				if(op == 2)
				{
					memset(cold,0,sizeof(bool) * (n + 1));
					zhi = 0;
				}
				if(op == 3)
					printf(cold[x] ? "wrxcsd\n" : "orzFsYo\n");	
			}
			return 0;
		}
		dfs(1,0); RMQ();
		try(tim,1,m)
		{
			register int op = get(),x = get();
			if(op == 1)
			{
				d[++zhi] = xin_data(tim,x);
			}
			if(op == 2)
			{
				zhi = 0;
			}
			if(op == 3)
			{
				bool ok = 1;
				try(i,1,zhi)
				{
					register int ks = tim - d[i].tim,dis = distance(x,d[i].pos);
					if(ks >= dis) {ok = 0;break;}
				}
				puts(ok ? "orzFsYo" : "wrxcsd");
			}
		}
		return 0;
	}
}
signed main(){return xin::main();}

牛半仙的妹子序列

似乎是極長上升子序列的板子。

然而我不會。。。

然後 \(gg\) 了,直接這個題目抱 \(\color{red}{0}\) 了。

用線段樹維護這個玩意,似乎和昨天的第二題有些相似。



#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)
namespace xin_io
{
	#define scanf nb = scanf
	#define debug cout<<"debug"<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<2,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf,output[100]; FILE *xinnb;int nb;typedef long long ll; typedef unsigned long long ull;
	void openfile() {xinnb = freopen("t.txt","r",stdin);} void outfile() {xinnb = freopen("o.txt","w",stdout);}
	inline int get()
	{
		register int s = 0,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 s * f;
	}
	template<typename type>inline void write(type x,char out)
	{
		if(!x) return putchar('0'),putchar(out),void(); if(x < 0) putchar('-'),x = -x;
		register int cnt = 0;while(x) output[++cnt] = x % 10,x /= 10; 
		throw(i,cnt,1) putchar(output[i] xor 48);return putchar(out),void();
	}
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7,mod = 998244353; static const ll llinf = 1e17+7;
namespace xin
{
	int n;
	int c[maxn],pos[maxn];
	int f[maxn],maxx;
	class xin_segment
	{
		private:
			#define ls(fa) (fa << 1)
			#define rs(fa) (fa << 1 | 1)
			int lim(int fa,int val)
			{
				if(t[fa].tag) return t[fa].s > val ? f[t[fa].s] : 0; 
				return t[rs(fa)].s < val ? lim(ls(fa),val) : (t[fa].lans + lim(rs(fa),val)) % mod;
			}
			inline void up(int fa)
			{
				t[fa].s = std::max(t[ls(fa)].s,t[rs(fa)].s);
				t[fa].lans = lim(ls(fa),t[rs(fa)].s);
			}
		public:
			class xin_tree{public:int s,lans,tag;}t[maxn];
			void build(int fa,int l,int r)
			{
				if(l == r) return t[fa].tag = 1,void(); //tag the leave point
				register int mid = l + r >> 1;
				build(ls(fa),l,mid); build(rs(fa),mid+1,r);
			}
			void modify(int fa,int l,int r,int pos,int val)
			{
				if(pos > r or pos < l) return;
				if(l == r) return t[fa].s = val,void();
				register int mid = l + r >> 1;
				modify(ls(fa),l,mid,pos,val); modify(rs(fa),mid+1,r,pos,val);
				up(fa);
			}
			int query(int fa,int l,int r,int ql,int qr)
			{
				if(ql > r or qr < l) return 0;
				if(ql <= l and qr >= r)
				{
					register int temp = maxx; maxx = std::max(maxx,t[fa].s);
					return lim(fa,temp);
				}
				register int mid = l + r >> 1,res = 0;
				res = (res + query(rs(fa),mid+1,r,ql,qr)) % mod; res = (res + query(ls(fa),l,mid,ql,qr)) % mod;
				return res;
			}
	}t;
	class xin_bit
	{
		private:
			#define lowbit(x) (x & -x)
		public:
			int s[maxn];
			inline void add(int x,int val)
			{for(register int i=x;i<=n;i+=lowbit(i)) s[i] += val;}
			inline int ask(int x)
			{int res = 0;for(register int i=x;i;i-=lowbit(i)) res += s[i];return res;}
	}bit;
	inline short main()
	{
	#ifndef ONLINE_JUDGE
		openfile();
	#endif
		n = get(); try(i,1,n) c[i] = get(),pos[c[i]] = i;
		t.build(1,1,n);
		try(i,1,n)
		{
			register int x = pos[i]; maxx = 0;
			f[i] = t.query(1,1,n,1,x);
			if(!f[i]) f[i] = 1;
			t.modify(1,1,n,x,i);
		}
		int ans = 0;
		throw(i,n,1)
		{
			if(bit.ask(n) == bit.ask(pos[i])) ans = (ans + f[i]) % mod;
			bit.add(pos[i],1);
		}
		cout<<ans<<endl;
		return 0;
	}
}
signed main(){return xin::main();}