NOI2022联合省选 day2代码

3 篇文章 0 订阅
1 篇文章 0 订阅

注:由于官方数据还没公布,所以代码不一定保熟
本来想在上一篇题解里放代码,但是这样文章就太长了,所以新开一篇文章放代码

d2t1:

#include<bits/stdc++.h>
#define gc getchar()
#define pc putchar
#define li long long
using namespace std;
inline li read(){
	li x = 0;
	int y = 0,c = gc;
	while(c < '0' || c > '9') y = c,c = gc;
	while(c >= '0' && c <= '9') x = x * 10 + c - '0',c = gc;
	return y == '-' ? -x : x;
}
inline void prt(li x){
	if(x >= 10) prt(x / 10);
	pc(x % 10 + '0');
}
inline void print(li x){
	if(x < 0) pc('-'),x = -x;
	prt(x);
}
inline void file(char *s){
	char c[50];
	sprintf(c,"%s.in",s);
	freopen(c,"r",stdin);
	sprintf(c,"%s.out",s);
	freopen(c,"w",stdout);
}
int p[2010],cnt,n,m,dy[2010],wei[10010];
bool notp[2010];
int sl[8200][310],ss[2010],a[310],k,zc[2010],bg[2010],tto[8210];
const int mo = 998244353;
li mi[1000010];
bool vis[2010];
int main(){
	//file("card");
	int i,j,x,l;
	for(i = 1;i < (1 << 13);++i) wei[i] = wei[i >> 1] ^ (i & 1);
	notp[1] = 1;
	for(i = 2;i <= 2000;++i){
		if(!notp[i]) p[++cnt] = i,dy[i] = cnt;
		for(j = 1;j <= cnt && i * p[j] <= 2000;++j){
			notp[i * p[j]] = 1;
			if(i % p[j] == 0) break;
		}
	}
	n = read();
	mi[0] = 1;for(i = 1;i <= n;++i) mi[i] = mi[i - 1] * 2 % mo;
	for(i = 1;i <= n;++i){
		++ss[read()];
	} 
	for(i = 14;i <= cnt;++i) for(j = 1;p[i] * j <= 2000;++j) bg[p[i] * j] = i;
	for(i = 1;i <= 2000;++i) for(j = 1;j <= 13;++j) 
		if(i % p[j] == 0) zc[i] |= (1 << j - 1);
	for(i = 0;i < (1 << 13);++i){//不能出现的因子集合 
		for(j = 1;j <= 2000;++j) if((i & zc[j]) == 0){
			sl[i][bg[j]] += ss[j];
			tto[i] += ss[j];
		}
	}
	m = read();
	li qqq = 0;
	for(i = 1;i <= m;++i){
		k = read();
		int r = 0,q = 0;
		memset(vis,0,sizeof(vis));
		for(j = 1;j <= k;++j){
			x = read();
			if(vis[x]) continue;
			vis[x] = 1;
			if(x <= 41) q |= 1 << (dy[x] - 1);
			else a[++r] = dy[x];
		}
		li ans = 0;
		for(j = q;;j = (j - 1) & q){
			int *g = sl[j];
			li tmp = 1;
			int oo = tto[j];
			for(l = 1;l <= r;++l){
				(tmp *= mi[g[a[l]]] - 1) %= mo;
				oo -= g[a[l]];
			}
			(tmp *= mi[oo]) %= mo;
			if(wei[j]) ans -= tmp;
			else ans += tmp;
			if(!j) break;
		}
		print((ans % mo + mo) % mo);pc('\n');
		
	}
	return 0;
}

d2t2:

#include<bits/stdc++.h>
#define gc getchar()
#define pc putchar
#define li long long
using namespace std;
inline li read(){
	li x = 0;
	int y = 0,c = gc;
	while(c < '0' || c > '9') y = c,c = gc;
	while(c >= '0' && c <= '9') x = x * 10 + c - '0',c = gc;
	return y == '-' ? -x : x;
}
inline void prt(li x){
	if(x >= 10) prt(x / 10);
	pc(x % 10 + '0');
}
inline void print(li x){
	if(x < 0) pc('-'),x = -x;
	prt(x);
}
inline void file(char *s){
	char c[50];
	sprintf(c,"%s.in",s);
	freopen(c,"r",stdin);
	sprintf(c,"%s.out",s);
	freopen(c,"w",stdout);
}
int n,a[500010],x,y;
char c[1000010];
vector<li> p[500010];
multiset<li> ss;
int mx;
li wk(int qs){
	int i,j;
	li qjmx = 0;int mxwz = 0;bool fg = 0;
	li ans = 0,mm,nn,cd;
	int sz,sl = ss.size();
	for(i = qs;i <= mx;++i){//找全局最大值,值为qjmx,位置为mxwz 
		sz = p[i].size();
		if(sz > 1) fg = 1;
		if(fg){
			if(p[i][sz - 1] >= qjmx){
				qjmx = p[i][sz - 1];
				mxwz = i;
			}
		}
	} 
	for(i = qs;i <= n;++i){
		//每一层用最小的把剩下的放进去,最后用最大的把最小的放进去
		int sz = i <= mx ? p[i].size() : 0;
		sl += sz;
		if(sl <= 1){sl = 0;continue;} 
		for(j = 0;j < p[i].size();++j) ss.insert(p[i][j]);
		mm = *ss.begin();//当前最小值 
		nn = *ss.rbegin();//当前最大值 
		if(i < mxwz){//还没遇到最大值 
			ans += mm * (sl - 2) + nn;//这一层的权值是mn*(sl-2)+mx
			--sl;ss.erase(ss.find(nn));//这一层留下最大值 
		} 
		else{//已经遇到了最大值 
			cd = *(++ss.rbegin());//当前次大值 
			ans += mm * (sl - 2) + cd;//这一层的权值是mn*(sl-2)+cd
			--sl;ss.erase(ss.find(cd));//这一层留下次大值 
		} 
	}
	ss.clear();
	return ans;
}
int main(){
	//file("bracket");
	int i,j;
	n = read();x = read();y = read();
	scanf("%s",c + 1);
	int nw = 0;
	for(i = 1,j = 1;i <= n;++i,++j){
		while(c[j] == ')') --nw,++j;
		p[++nw].push_back(read());
		mx = max(mx,nw);
	}
	for(i = 1;i <= mx;++i) sort(p[i].begin(),p[i].end());
	li ans = 0,mm = 1e9,nn = 0,tot = 0;
	int sl = 0;
	int qs = 0;
	for(qs = 1;qs <= mx;++qs) if(p[qs].size() > 1) break; 
	if(qs == mx + 1){
		pc('0');pc('\n');return 0;
	} 
	if(x == 1 && y == 1){//每层用最小的把别的放进去,在外面留一个最大的 
		for(i = qs;i <= n;++i){
			int sz = i <= mx ? p[i].size() : 0;
			sl += sz;
			if(sl <= 1){sl = 0;continue;} 
			for(j = 0;j < p[i].size();++j){
				tot += p[i][j];
				ss.insert(p[i][j]);
			} 
			mm = *ss.begin();//当前最小值 
			nn = *ss.rbegin();//当前最大值 
			ans += tot + mm * (sl - 2);//这一层的权值是sum+mn*(sl-2) 
			--sl;tot -= nn;ss.erase(ss.find(nn));//外面留下最大值 
		}
	}
	else if(y == 1){//直接把小的扔进去,外面留一个最大值 
		for(i = qs;i <= n;++i){
			int sz = i <= mx ? p[i].size() : 0;
			sl += sz;
			if(sl <= 1){sl = 0;continue;} 
			for(j = 0;j < p[i].size();++j){
				tot += p[i][j];
				ss.insert(p[i][j]);
			} 
			mm = *ss.begin();//当前最小值 
			nn = *ss.rbegin();//当前最大值 
			ans += tot - nn;//这一层的权值是sum-mx
			--sl;tot -= nn;ss.erase(ss.find(nn));//外面留下最大值 
		}
	}
	else if(x == 1){//两种贪心取最优 
		ans = wk(qs); //贪心1:把全局最大值放进最里层
		//贪心2:如果开局是2 1 1...1 k结构,把前面这些层的最小值放进k这一层,后续不变 
		int o;for(o = qs + 1;o <= mx;++o) if(p[o].size() != 1) break;
		if(p[qs].size() == 2){//只有全局最大出现在前半段时可能会有影响 
			tot = 0;mm = 1e9;
			for(i = qs;i < o;++i){
				for(j = 0;j < p[i].size();++j){
					tot += p[i][j];
					mm = min(mm,p[i][j]);
				}
			}
			ss.insert(mm);
			li an = wk(o);
			ans = min(ans,an + tot - mm);
		} 
	}
	print(ans);pc('\n');
	return 0;
}

d2t3:

#include<bits/stdc++.h>
#define gc getchar()
#define pc putchar
#define li long long
#define mp make_pair
#define pli pair<li,int>
#define fi first
#define se second
#define pb push_back
using namespace std;
inline li read(){
	li x = 0;
	int y = 0,c = gc;
	while(c < '0' || c > '9') y = c,c = gc;
	while(c >= '0' && c <= '9') x = x * 10 + c - '0',c = gc;
	return y == '-' ? -x : x;
}
inline void prt(li x){
	if(x >= 10) prt(x / 10);
	pc(x % 10 + '0');
}
inline void print(li x){
	if(x < 0) pc('-'),x = -x;
	prt(x);
}
inline void file(char *s){
	char c[50];
	sprintf(c,"%s.in",s);
	freopen(c,"r",stdin);
	sprintf(c,"%s.out",s);
	freopen(c,"w",stdout);
}
int n;
#define M 5005
li a[M];
int fa[M],ls[M],rs[M];
vector<li> f[M][M];
vector<int> ch[M];
int dpt[M];
bool inzs[M][M];
li vl[M],vr[M],dl[M],dr[M],dvl[M],dvr[M];
void dfs(int x){
	if(!x) return;
	int lc = ls[x],rc = rs[x];
	dfs(lc);dfs(rc);
	dpt[x] = max(dpt[lc],dpt[rc]) + 1;
	int i = 0,j = 0,k,l,o,p,q,d,dt = dpt[x];
	li ax = a[x];
	ch[x].pb(x);
	int szl = ch[lc].size(),szr = ch[rc].size();
	while(i < szl && j < szr){
		if(a[ch[lc][i]] < a[ch[rc][j]]) ch[x].pb(ch[lc][i++]);
		else ch[x].pb(ch[rc][j++]);
	}
	while(i < szl) ch[x].pb(ch[lc][i++]);
	while(j < szr) ch[x].pb(ch[rc][j++]);
	for(i = 1;i < ch[x].size() && ax > a[ch[x][i]];++i) swap(ch[x][i - 1],ch[x][i]);
	for(i = 0;i < ch[x].size();++i) inzs[x][ch[x][i]] = 1;
	
	if(!lc) f[x][x].pb(ax);
	
	if(lc && !rc){
		f[x][x].resize(dt);
		for(d = 0;d < dt;++d) f[x][x][d] = 1e18l;
		for(i = 0;i < szl;++i){
			p = ch[lc][i];
			for(d = 1;d <= f[lc][p].size();++d){
				f[x][x][d] = min(f[x][x][d],f[lc][p][d - 1] + ax);
			}
		}
		for(i = 0;i < szl;++i){
			p = ch[lc][i];
			f[x][p].pb(1e18l);
			for(d = 0;d < f[lc][p].size();++d){
				f[x][p][0] = min(f[x][p][0],f[lc][p][d] + ax * (d + 1) + a[p]);
			}
		}
	}
	
	if(rc){
		memset(vl,0x1f,sizeof(vl));
		memset(vr,0x1f,sizeof(vr));
		memset(dl,0x1f,sizeof(dl));
		memset(dr,0x1f,sizeof(dr));
		memset(dvl,0x1f,sizeof(dvl));
		memset(dvr,0x1f,sizeof(dvr));
		for(i = 0;i < szl;++i){
			p = ch[lc][i];
			for(d = 0;d < f[lc][p].size();++d){
				vl[p] = min(vl[p],f[lc][p][d] + ax * (d + 1));
				dl[d] = min(dl[d],f[lc][p][d]);
			} 
			for(d = 0;d < dpt[rc];++d){
				dvr[d] = min(dvr[d],vl[p] + a[p] * (d + 1));
			}
		}
		for(j = 0;j < szr;++j){
			q = ch[rc][j];
			for(d = 0;d < f[rc][q].size();++d){
				vr[q] = min(vr[q],f[rc][q][d] + ax * (d + 1));
				dr[d] = min(dr[d],f[rc][q][d]);
			}
			for(d = 0;d < dpt[lc];++d){
				dvl[d] = min(dvl[d],vr[q] + a[q] * (d + 1));
			}
		}
		
		
		for(i = 0;i < szl;++i){
			p = ch[lc][i];
			f[x][p].resize(dpt[rc] + 1);
			f[x][p][0] = 1e18l;
			for(d = 1;d <= dpt[rc];++d){
				f[x][p][d] = vl[p] + dr[d - 1] + a[p];
			}
		}
		for(j = 0;j < szr;++j){
			q = ch[rc][j];
			f[x][q].resize(dpt[lc] + 1);
			f[x][q][0] = 1e18l;
			for(d = 1;d <= dpt[lc];++d){
				f[x][q][d] = vr[q] + dl[d - 1] + a[q];
			}
		}
		
		
		f[x][x].resize(dt);
		for(d = 0;d < dt;++d) f[x][x][d] = 1e18l;
		for(i = 0;i < szl;++i){
			p = ch[lc][i];
			li tmp = 1e18l;
			for(o = 0;o < dpt[rc];++o) tmp = min(tmp,dr[o] + a[p] * (o + 1));
			for(d = 0;d < f[lc][p].size();++d){
				f[x][x][d + 1] = min(f[x][x][d + 1],f[lc][p][d] + tmp + a[x]);
				f[x][p][0] = min(f[x][p][0],dvl[d] + f[lc][p][d] + a[p]);
			}
		}
		for(j = 0;j < szr;++j){
			q = ch[rc][j];
			li tmp = 1e18l;
			for(o = 0;o < dpt[lc];++o) tmp = min(tmp,dl[o] + a[q] * (o + 1));
			for(d = 0;d < f[rc][q].size();++d){
				f[x][x][d + 1] = min(f[x][x][d + 1],f[rc][q][d] + tmp + a[x]);
				f[x][q][0] = min(f[x][q][0],dvr[d] + f[rc][q][d] + a[q]);
			}
		}
	}
}
int main(){
	//file("mis");
	int i,k;
	n = read();
	for(i = 1;i <= n;++i) a[i] = read();
	for(i = 2;i <= n;++i){
		k = read();fa[i] = k;
		if(ls[k]) rs[k] = i;
		else ls[k] = i;
	}
	dfs(1);
	li ans = 1e18l;
	for(i = 0;i < dpt[1];++i) ans = min(ans,f[1][1][i] + a[1] * (i - 1));
	print(ans);pc('\n');
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值