NOIP模拟77

Posted HZOI_LYM

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP模拟77相关的知识,希望对你有一定的参考价值。

T1:

  30pts:暴力枚举点对

  70pts:考虑O(n)算法,优化枚举点对过程,考虑对于i,如何确定[l,i]区间内maxor

    可以按位考虑,求出i二进制下“补位”x,问题转化为判断[l,i]区间与x最大交,

    在[l,r]区间枚举过程中利用sum记录所有出现过的二进制位,与x取交即可

  100pts:考虑优化70分过程,由于或的性质,可以贪心选择高位,于是问题转化为

    固定r,求解maxor,考虑优化上述判断过程,显然方法为二进制考虑,我们

    只需要判断[l,r]区间是否存在该二进制位,暴力枚举即可O(log^2w)

代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define I long long
 4 #define C char
 5 #define B bool
 6 #define V void
 7 #define D double
 8 #define LL long long
 9 #define UI unsigned int
10 #define UL unsigned long long
11 #define P pair<I,I>
12 #define MP make_pair
13 #define a first
14 #define b second
15 #define lowbit(x) (x & -x)
16 #define debug cout << "It\'s Ok Here !" << endl;
17 #define FP(x) freopen (#x,"r",stdin)
18 #define FC(x) freopen (#x,"w",stdout)
19 #define memset(name,val,typ,len) memset (name,val,sizeof (typ) * len)
20 #define Mod1(a,b) (a = a + b > mod ? a + b - mod : a + b)
21 #define Mod2(a,b) (a = a - b <  0  ? a - b + mod : a - b)
22 inline I read () {
23     I x(0),y(1); C z(getchar());
24     while (!isdigit(z)) { if (z == \'-\') y = -1; z = getchar(); }
25     while ( isdigit(z))  x = x * 10 + (z ^ 48), z = getchar();
26     return x * y;
27 }
28 inline V Max (I &a,I &b) { a = a > b ? a : b; }
29 inline V Min (I &a,I &b) { a = a < b ? a : b; }
30 inline I max (I &a,I &b) { return a > b ? a : b; }
31 inline I min (I &a,I &b) { return a < b ? a : b; }
32 inline V swap (I &a,I &b) { a ^= b, b ^= a, a ^= b; }
33 inline I abs (I &a) { return a >= 0 ? a : -a; }
34 inline P operator + (const P &a,const P &b) {
35     return MP (a.a + b.a,a.b + b.b);
36 }
37 inline P operator - (const P &a,const P &b) {
38     return MP (a.a - b.a,a.b - b.b);
39 }
40 signed main () {
41     FP (maxor.in), FC (maxor.out);
42     I T (read ());
43     while (T -- ) {
44         B buc[63];
45         I l (read ()), r (read ()), ans (0);
46         memset (buc,0,B,63);
47         for (I i(0);i <  63; ++ i) {
48             I s (1ll << i);
49             if (s >= l && s <= r) {
50                 buc[i] = 1; continue;
51             }
52             for (I j(62);j >= 0; -- j) {
53                 if ((s | (1ll << j)) <= r)
54                     s |= (1ll << j);
55                 if (s >= l && s <= r) {
56                     buc[i] = 1; break;
57                 }
58             }
59         }
60         for (I i(0);i <  63; ++ i) if (buc[i])
61             ans |= (1ll << i);
62         printf ("%lld\\n",ans);
63     }
64 }

T2:

  50pts:暴力Dfs枚举选择即可

  60~70pts:考虑问题实际上是求方案数k / (1 << n) >= p,观察到值域并不大

    背包转移方案数即可,需要卡空间

  100pts:考虑再次进行优化,考虑上述过程实际上是求区间第k大值使得所有

    小于等于k的方案数大于等于(1 << n) * p,在观察数据范围,可以考虑

    meet in the middle ,将两侧所有方案数进行记录,二分第k大值,计算

    满足条件的方案数进行判断即可

代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define I int
 4 #define C char
 5 #define B bool
 6 #define V void
 7 #define D double
 8 #define LL long long
 9 #define UI unsigned int
10 #define UL unsigned long long
11 #define P pair<I,I>
12 #define MP make_pair
13 #define a first
14 #define b second
15 #define lowbit(x) (x & -x)
16 #define debug cout << "It\'s Ok Here !" << endl;
17 #define FP(x) freopen (#x,"r",stdin)
18 #define FC(x) freopen (#x,"w",stdout)
19 #define memset(name,val,typ,len) memset (name,val,sizeof (typ) * len)
20 #define Mod1(a,b) (a = a + b > mod ? a + b - mod : a + b)
21 #define Mod2(a,b) (a = a - b <  0  ? a - b + mod : a - b)
22 D p;
23 LL sch;
24 I n,tot,cnt,ans,tmp1,sigma,a[25],b[1 << 20],c[1 << 20];
25 inline I read () {
26     I x(0),y(1); C z(getchar());
27     while (!isdigit(z)) { if (z == \'-\') y = -1; z = getchar(); }
28     while ( isdigit(z))  x = x * 10 + (z ^ 48), z = getchar();
29     return x * y;
30 }
31 inline V Max (I &a,I b) { a = a > b ? a : b; }
32 inline V Min (I &a,I b) { a = a < b ? a : b; }
33 inline I max (I &a,I &b) { return a > b ? a : b; }
34 inline I min (I &a,I &b) { return a < b ? a : b; }
35 inline V swap (I &a,I &b) { a ^= b, b ^= a, a ^= b; }
36 inline I abs (I &a) { return a >= 0 ? a : -a; }
37 inline P operator + (const P &a,const P &b) {
38     return MP (a.a + b.a,a.b + b.b);
39 }
40 inline P operator - (const P &a,const P &b) {
41     return MP (a.a - b.a,a.b - b.b);
42 }
43 V Dfs1 (I num) {
44     if (num > tmp1) 
45         return b[cnt++] = sigma, V ();   
46     sigma += a[num], Dfs1 (num + 1), sigma -= a[num];
47     Dfs1 (num + 1);
48 }
49 signed main () {
50     n = read (); scanf ("%lf",&p);
51     sch = ceil (p * (1ll << n));
52     tmp1 = n >> 1; ans = INT_MAX;
53     for (I i(1);i <= tmp1; ++ i)
54         a[i] = read ();
55     Dfs1 (1); sort (b,b + cnt); 
56     memcpy (c,b,sizeof b);
57     tmp1 = n - tmp1; tot = cnt, cnt = 0;
58     for (I i(1);i <= tmp1; ++ i)
59         a[i] = read ();
60     Dfs1 (1); sort (b,b + cnt);
61     I l (0), r (b[cnt - 1] + c[tot - 1]);
62     while (l < r) { I mid (l + r >> 1);
63         I p1 (0), p2 (tot - 1); LL sum (0);
64         while (p1 < cnt) {
65             while (b[p1] + c[p2] >  mid && p2 >= 0) p2 -- ;
66             sum += tot - p2 - 1; p1 ++ ;
67         }
68         (1ll << n) - sum >= sch ? (Min (ans,mid), r = mid) : l = mid + 1;
69     }
70     printf ("%d\\n",ans);
71 }

T3:

  计算空间发现bitset刚好,利用bitset判断连通性,枚举中转点,再枚举贡献点即可

代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define I int
 4 #define C char
 5 #define B bool
 6 #define V void
 7 #define D double
 8 #define LL long long
 9 #define UI unsigned int
10 #define UL unsigned long long
11 #define P pair<I,I>
12 #define MP make_pair
13 #define a first
14 #define b second
15 #define lowbit(x) (x & -x)
16 #define debug cout << "It\'s Ok Here !" << endl;
17 #define FP(x) freopen (#x,"r",stdin)
18 #define FC(x) freopen (#x,"w",stdout)
19 #define memset(name,val,typ,len) memset (name,val,sizeof (typ) * len)
20 #define Mod1(a,b) (a = a + b > mod ? a + b - mod : a + b)
21 #define Mod2(a,b) (a = a - b <  0  ? a - b + mod : a - b)
22 const I N = 3e4 + 3;
23 I n,m,t,w[N];
24 LL MA(-1);
25 LL sum;
26 vector <I> to[N];
27 vector <bitset <N>> s;
28 inline I read () {
29     I x(0),y(1); C z(getchar());
30     while (!isdigit(z)) { if (z == \'-\') y = -1; z = getchar(); }
31     while ( isdigit(z))  x = x * 10 + (z ^ 48), z = getchar();
32     return x * y;
33 }
34 inline V Max (LL &a,LL b) { a = a > b ? a : b; }
35 inline V Min (I &a,I b) { a = a < b ? a : b; }
36 inline I max (I &a,I &b) { return a > b ? a : b; }
37 inline I min (I &a,I &b) { return a < b ? a : b; }
38 inline V swap (I &a,I &b) { a ^= b, b ^= a, a ^= b; }
39 inline I abs (I &a) { return a >= 0 ? a : -a; }
40 inline P operator + (const P &a,const P &b) {
41     return MP (a.a + b.a,a.b + b.b);
42 }
43 inline P operator - (const P &a,const P &b) {
44     return MP (a.a - b.a,a.b - b.b);
45 }
46 signed main () {
47     FP (link.in), FC (link.out);
48     n = read (), m = read (), t = read ();
49     s.resize (n + 1);
50     for (I i(1);i <= m; ++ i) {
51         I x (read ()), y (read ());
52         s[x][y] = s[y][x] = 1;
53         to[x].push_back (y), to[y].push_back (x);
54     }
55     for (I i(1);i <= n; ++ i) w[i] = read ();
56     for (I i(1);i <= n; ++ i) 
57         for (I j(0);j < to[i].size (); ++ j)
58             for (I k(j + 1);k < to[i].size (); ++ k) if (!s[to[i][j]][to[i][k]])
59                 Max (MA,1ll * w[to[i][j]] * w[to[i][k]]), sum += w[to[i][j]] * w[to[i][k]]; 
60     printf ("%lld\\n%lld\\n",t != 2 ? MA : 0,t != 1 ? sum << 1 : 0);
61 }

T4:

  70pts:bitset暴力维护区间关系即可

  100pts:题目关键信息之一为每个原件只参与一次融合,因此可以想到树形结构,

    问题转化为判断两点树上关系,首先若无祖先关系puts (0)即可

    考虑若y为x祖先,那么满足条件为x到y路径上只存在或运算

    反之,为y到x路径上只存在与运算,考虑如何维护

    首先只需要判断祖先关系,于是可以利用dfn序进行判断,区间是否有交即可

    (若求具体祖先则只能树剖或倍增进行维护)

    考虑如何维护一条链上的操作,树剖+线段树显然是可以的,考虑一种新的维护方法

    由于需要维护的是与或关系,考虑使用并查集进行关系维护,分别建立与或并查集

    利用信息传递即可

代码如下:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define I int
  4 #define C char
  5 #define B bool
  6 #define V void
  7 #define D double
  8 #define LL long long
  9 #define UI unsigned int
 10 #define UL unsigned long long
 11 #define P pair<I,I>
 12 #define MP make_pair
 13 #define a first
 14 #define b second
 15 #define lowbit(x) (x & -x)
 16 #define debug cout << "It\'s Ok Here !" << endl;
 17 #define FP(x) freopen (#x,"r",stdin)
 18 #define FC(x) freopen (#x,"w",stdout)
 19 #define memset(name,val,typ,len) memset (name,val,sizeof (typ) * len)
 20 #define Mod1(a,b) (a = a + b > mod ? a + b - mod : a + b)
 21 #define Mod2(a,b) (a = a - b <  0  ? a - b + mod : a - b)
 22 const I N = 5e5 + 3;
 23 I n,m,k,x,y,ban;
 24 I tot,head[N],to[N],nxt[N],In[N];
 25 I cnt,dfn[N],size[N];
 26 vector <P> que;
 27 inline I read () {
 28     I x(0),y(1); C z(getchar());
 29     while (!isdigit(z)) { if (z == \'-\') y = -1; z = getchar(); }
 30     while ( isdigit(z))  x = x * 10 + (z ^ 48), z = getchar();
 31     return x * y;
 32 }
 33 inline V Max (I &a,I &b) { a = a > b ? a : b; }
 34 inline V Min (I &a,I &b) { a = a < b ? a : b; }
 35 inline I max (I &a,I &b) { return a > b ? a : b; }
 36 inline I min (I &a,I &b) { return a < b ? a : b; }
 37 inline V swap (I &a,I &b) { a ^= b, b ^= a, a ^= b; }
 38 inline I abs (I &a) { return a >= 0 ? a : -a; }
 39 inline P operator + (const P &a,const P &b) {
 40     return MP (a.a + b.a,a.b +

2021.11.18-NOIP模拟信心赛

前言

太蒟蒻了,信心赛打的都快没信心了,giao

T1\\(\\color{green}100\\)题目

T1作为简单的签到题,直接先枚举所有的流量再用dijkstra跑这么多遍就可以了

#include<bits/stdc++.h>
#define M 2100
#define N 1100
#define inf 0x7f7f7f7f
using namespace std;
int n,m,maxx=-15;
int first[M],nex[M],to[M],w[M],f[M],tot;
int dis[N];
bool vis[N];
priority_queue<pair<int,int> >q;
//=======================================================
inline int read(){
	int p=0,f=1;
	char c=getchar();
	while(!isdigit(c)){if(c==\'-\')f=-1;c=getchar();}
	while(isdigit(c)){p=p*10+c-\'0\';c=getchar();}
	return p*f;
}
//========================================================
inline void add(int x,int y,int z,int q){
	nex[++tot]=first[x];
	first[x]=tot;
	to[tot]=y;
	w[tot]=z;
	f[tot]=q;
}
//========================================================
inline void dijkstra(){
	for(int x=1;x<=1000;x++){
		for(int i=1;i<=n;i++){
			dis[i]=inf;
			vis[i]=0;
		}
		q.push(make_pair(0,1));
		dis[1]=0;	
		while(!q.empty()){
			int u=q.top().second;
			q.pop();
			if(vis[u])continue;
			vis[u]=1;
			for(int i=first[u];i;i=nex[i]){
				int v=to[i];
				if(f[i]<x)continue;
				if(dis[u]+w[i]<dis[v]){
					dis[v]=dis[u]+w[i];
					if(!vis[v]){
						q.push(make_pair(-dis[v],v));
					}
				}
			}
		}
		if(dis[n]!=inf)
			maxx=max(maxx,x*1000000/dis[n]);
	}
}
//========================================================
int main(){
	n=read(),m=read();
	int a,b,c,f;
	for(int i=1;i<=m;i++){
		a=read(),b=read(),c=read(),f=read();
		add(a,b,c,f);
		add(b,a,c,f);
	}
	dijkstra();
	cout<<maxx<<endl;
	return 0;
}

T2\\(\\color{red}0\\)题目

明明第二天比第一题还简单简单我却做不出来

一开始在哪里想建图然后\\(bfs\\)然后小样例过了,大样例却挂了

结果直接用一个并查集分成两个集合就好了(有两种牛奶)

#include<bits/stdc++.h>
using namespace std;
#define N 100010
int n,m;
char s[N];
int f[N];
int ans[N];
//=====================================================
inline int read(){
	int p=0,f=1;
	char c;
	while(!isdigit(c)){if(c==\'-\')f=-1;c=getchar();}
	while(isdigit(c)){p=p*10+c-\'0\';c=getchar();}
	return p*f;
}
//======================================================
int gf(int x){
	if(x == f[x]) return x;
	return f[x] = gf(f[x]);
}
//======================================================
void hb(int x, int y){
	f[gf(x)] = gf(y);
}
//======================================================
int main(){
	n=read(),m=read();
	scanf("%s",s+1);
	int x,y;
	for(int i=1;i<=n;i++)f[i]=i;
	for(int i=1;i<n;i++){
		x=read(),y=read();
		if(s[x]==s[y])
			hb(x,y);
	}
	for(int i=1;i<=m;i++){
		char c;
		x=read(),y=read(),cin>>c;
		if(gf(x)==gf(y)&&s[x]!=c)ans[i]=0;
		else ans[i]=1;
	}
	for(int i=1;i<=m;i++)cout<<ans[i];
	return 0;
}

T3\\(\\color{red}0\\)题目

第二题都没做出来自然第三题也做不出来

题意:

求一颗树\\(u\\)\\(v\\)的路径上有无某颜色的点

先跑一遍dfs,再求出\\(u\\)\\(v\\)的最近公共祖先,这样就可以得到\\(u\\)\\(v\\)的路径,然后用结构体和vector存储查询的颜色,最近公共祖先以及该点的编号,

最后再来一遍dfs,这一遍相当于把颜色按照节点的深度进行赋值,然后枚举点因为刚才记录了该点所要查询的颜色以及最近公共祖先,而且\\(u\\)\\(v\\)都记录了,所以如果该点颜色深度大于最近公共祖先的深度,就说明一定能够经过,就把\\(ans[now.id]=1\\)

第三题代码复杂度\\(O\\)\\(n\\log n\\)

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 100,M = 2e5 + 100;
const int maxdep=24;
int n,m;
int first[M],to[M],nex[M],tot;
int val[N],dep[N],faz[N][maxdep+1],ans[N];
struct mpair{
	int col,top,id;
};
vector<mpair> vec[N];
//==============================================================
inline int read(){
	int p=0,f=1;
	char c=getchar();
	while(!isdigit(c)){if(c==\'-\')f=-1;c=getchar();}
	while(isdigit(c)){p=p*10+c-\'0\';c=getchar();}
	return p*f;
}
//==============================================================
inline void add(int x,int y){
	nex[++tot]=first[x];
	first[x]=tot;
	to[tot]=y;
}
//==============================================================
void dfs1(int u){
	for(int i=1;i<=maxdep;i++)faz[u][i]=faz[faz[u][i-1]][i-1];
	for(int i=first[u];i;i=nex[i]){
		int v=to[i];
		if(v==faz[u][0])continue;
		dep[v]=dep[u]+1;
		faz[v][0]=u;
		dfs1(v);
	}
}
//==============================================================
inline int lca(int x,int y){
	if(dep[x]<dep[y])swap(x,y);
	for(int i=maxdep;i>=0;i--)
		if(dep[faz[x][i]]>=dep[y])x=faz[x][i];
	if(x==y)return x;
	for(int i=maxdep;i>=0;i--)
		if(faz[x][i]!=faz[y][i])x=faz[x][i],y=faz[y][i];
	return faz[x][0];
}
//==============================================================
int tmp[N];
void dfs(int u){
	int lst=tmp[val[u]];
	tmp[val[u]]=dep[u];
	for(int i=0;i<vec[u].size();i++){
		mpair now=vec[u][i];
		if(tmp[now.col]>=dep[now.top])
			ans[now.id]=1;
	}
	for(int i=first[u];i;i=nex[i]){
		int v=to[i];
		if(v==faz[u][0])continue;
		dfs(v);
	}
	tmp[val[u]]=lst;
}
//==============================================================
int main(){
	n=read(),m=read();
	for(int i=1;i<=n;i++)val[i]=read();
	int x,y;
	for(int i=1;i<n;i++){
		x=read(),y=read();
		add(x,y);
		add(y,x);
	}
	dfs1(1);
	int c;
	for(int i=1;i<=m;i++){
		x=read(),y=read(),c=read();
		int l=lca(x,y);
		vec[x].push_back(mpair{c,l,i});
		vec[y].push_back(mpair{c,l,i});
	}
	memset(tmp,-1,sizeof(tmp));
	dfs(1);
	for(int i=1;i<=m;i++)cout<<ans[i];
	return 0;
}

今天就是集训的最后一天了,明天就是NOIP2021了,祝所有的OIer rp++

以上是关于NOIP模拟77的主要内容,如果未能解决你的问题,请参考以下文章

noip模拟赛 写代码

NOIP模拟赛16

NOIp模拟赛binary

XJOI NOIP模拟题1

神奇的幻方(NOIP2015)(真·纯模拟)

NOIp模拟赛value