Nov 21

依然是爆炸的一天,t1 没写好 100 -> 45,t2 倒是没有挂,t3 数据竟然是随机的,我的暴力跑的飞快,t4 竟然没有推出来无脑 dp, 看来我需要专门找一天疯狂推 dp 式子。

比赛层面

今天专注时间大概有两个小时?其他时间在玩 galgame 和在外边闲逛。

不要太过相信自己的贪心,即使证明出来也要对拍,一般贪心对拍不难写,有的时候策略即使是对的也会出现一些实现上或细节上的问题,s2oj 有传奇捆绑。

快读一定要快。

暴力如果发现有许许多多的剪枝可以加就尽量加,正经比赛没有绑包,很有可能出现一部分随机数据,一棵树硬生生向上跳也成为了 log 级别的。

这一次 t3 我的暴力预计是 50 分的,结果大胆优化到了 65 分,硬生生挤过了一个捆绑包,只能说感谢随机数据,明明可以把我卡到 1e10 的,但是随机就不好说了。

不知道为什么 t4 的无脑 dp 部分分并没有整出来,下次一定。

今天的 t2 我通过打表的方式加速了我想出来正解的过程,拜谢打表大法。

getchar_unlocked 是真的好快,在 T3 这种 time limit 大,输入极其多的题目中真的很牛逼,据说这个是和 fread 坐一桌的。

题目层面

S2OJ 2491

普通题

我们假设删的元素是 \(x,y\),新增的是 \(z=(x\oplus y)\)

因为最后的答案是 \(\sum 2^{a_i}\),这个东西同二进制有很好的贪心性质。

明显的 \(max(x,y)\ge z\)

所以我们发现如果两个数字的高处的位是一样的话就不行,而一共只有 60 二进制位的数字,我们发现如果这个东西如果 n > 60 就直接无解了,因为我们没有位置使得这些位都不一样了。

之后我们直接暴力跑 60 就行了。

代码↓

点击查看代码
#include <bits/stdc++.h>
#define int long long
#define getchar getchar_unlocked
using namespace std;
const int MN=1e6+116;
int n, a[MN];
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
        x=x*10+ch-'0',ch=getchar();
    return x*f;
}
void Solve(){
	n=read();
	for(int i=1; i<=n; ++i) a[i]=read();
	if(n>60){
		putchar('N');
		putchar('O');
		putchar('\n');
		return;		
	}		
	bool can=true;
	for(int i=1; i<=n&&can; ++i){
		for(int j=1; j<i&&can; ++j){
			if((a[i]^a[j])<=max(a[i],a[j])){
				can=false;
			}
		}
	}
	if(can){
		putchar('Y');
		putchar('E');
		putchar('S');
		putchar('\n');
	}
	else{
		putchar('N');
		putchar('O');
		putchar('\n');
	}
	return;
}
signed main(){
	int T; T=read(); while(T--) Solve();
	return 0;
}
/*
尼马的破涕
*/

S2OJ 2496

简单题

我们首先发现如果一个位置是正确的,我们就绝不动这个位置。

然后有两个情况,一个是交换可以使两个位置正确的,一个是交换可以是一个位置正确的。

再把所有前者都选上,之后讨论剩下的。

我们将所有位置 %4 看,如果一样视为一等。

找一个最大的同位置同字符的次数,我们选择把这个次数的位置留出来,这个样子我们就可以把这些次数省出来。

好题好做。

代码↓

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int MN=1e5+115;
/*
别假求求了,我什么都愿意做的
*/
unordered_map <char,int> trans;
int n; string s;
int cnt[5][5], ans=0;
void Read(){
	memset(cnt,0,sizeof(cnt));
	cin>>n>>s; s=' '+s;
	for(int i=1; i<=n+n+n+n; ++i){
		cnt[trans[s[i]]][i%4]++;
	}	
	return;
}
void Solve(){
	Read(); ans=0;
	cnt[1][1]=cnt[2][2]=cnt[3][3]=cnt[4][0]=0;
	for(int i=1; i<=4; ++i){//each ji
		int should=i%4;
		for(int j=1; j<=4; ++j){
			if(i==j) continue;
			ans+=min(cnt[i][j%4],cnt[j][should]);
			int val=min(cnt[i][j%4],cnt[j][should]);
			cnt[i][j%4]-=val;
			cnt[j][should]-=val;
		}
	};
	int miao=0, maxn=0;
	for(int i=1; i<=4; ++i){
		for(int j=0; j<=3; ++j){
			miao+=cnt[i][j];
			maxn=max(maxn,cnt[i][j]);
		}
	}
	cout<<ans+(miao-maxn)<<'\n';
	return;
}
int main(){
	//freopen("test.in","r",stdin);
	//freopen("test.out","w",stdout);
	trans['A']=1; trans['C']=2; trans['G']=3; trans['T']=4;
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int T; cin>>T; while(T--) Solve();
	return 0;
}
/*
啊?
打个表发现神秘规律过大样例?
不是
啊?
希望别假!
求求了
呜呜呜呜呜
如果我的打表做法没有假,我直接 js 到 noip

神人忧郁转换男~
过牌守护钢铁师~
对面铺场不要紧,
一张起义来兜底。
*/

S2OJ 2492

傻逼题。

为什么 noip 模拟赛会出现树链剖分大数据结构题?

不改这个玩意了,写了半天没调出来,放一下我美丽的暴力↓

点击查看代码
#include <bits/stdc++.h>
#define getchar getchar_unlocked
using namespace std;
const int MN=3e6+116;
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
        x=x*10+ch-'0',ch=getchar();
    return x*f;
}
struct Node{
	int nxt, to;
}node[MN];
int head[MN], tottt, fa[MN];
void insert(int u, int v){
	node[++tottt].to=v;
	node[tottt].nxt=head[u];
	head[u]=tottt; return;
}
int n, q, a[MN], depth[MN];
void Read(){
	n=read(); q=read();
	for(int i=1; i<=n; ++i) a[i]=read();
	for(int i=1; i<n; ++i){
		int u, v; u=read(); v=read();
		insert(u,v); insert(v,u);
	}
	return;
}
void dfs(int u, int father){
	fa[u]=father; depth[u]=depth[father]+1;
	for(int i=head[u];i;i=node[i].nxt){
		int v=node[i].to;
		if(v==father) continue;
		dfs(v,u);
	}
	return;
}
int LCA(int x, int y){
	if(depth[x]<depth[y]) swap(x,y);
	while(depth[x]!=depth[y]) x=fa[x];
	if(x==y) return x;
	while(fa[x]!=fa[y]) x=fa[x],y=fa[y];
	return fa[x];
}
int stk[MN], top=0;
bool work(int pos, int sum){
	if(pos==top) return (sum==24);
	if(sum>24) return false;
	if(work(pos+1,sum*stk[pos+1])) return true;
	else return work(pos+1,sum+stk[pos+1]);
}
int Query(int x, int y){
	top=0; int lca=LCA(x,y);
	vector <int> tmp; tmp.clear();
	while(x!=lca){
		stk[++top]=a[x];
		x=fa[x];
	}
	stk[++top]=a[lca];
	while(y!=lca){
		tmp.push_back(a[y]);
		y=fa[y];
	}
	reverse(tmp.begin(),tmp.end());
	for(auto v:tmp) stk[++top]=v;
	//cout<<'\n';
	//for(int i=1; i<=top; ++i) cout<<stk[i]<<" ";
	//cout<<'\n';
	if(!top) return 0;
	return work(1,stk[1]);
}
void Change(int x, int y){
	a[x]=y; return;
}
void Solve(){
	Read(); dfs(1,1);
	while(q--){
		int op, x, y;
		op=read(); x=read(); y=read();
		if(op==2){
			Change(x,y);
		}else{
			cout<<Query(x,y)<<'\n';
		}
	}
	return;
}
int main(){
	//freopen("test.in","r",stdin);
	//freopen("test.out","w",stdout);
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	Solve();
	return 0;
}
/*
加上剪纸大样例跑五秒,这个暴力有前途
看看能不能把大样例卡到 4 s
希望不尽尽是 20 pts
求求了
*/

S2OJ 2497

好题。

我们如果知道了在那个位置结束,我们一定是在保证能到达这个位置的情况下尽可能在前边打,因为体力如果跳过是损耗的,至于如果后边的留些体力过去会更优,我们就不断枚举结束位置,反悔贪心去选择就行了。

代码↓

点击查看代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MN=1e6+116;
int n, B, a[MN], b[MN], ans=0, A, res;
priority_queue <int> q;
void Read(){
	cin>>n>>B;
	for(int i=0; i<=n+1; ++i) a[i]=b[i]=0;
	for(int i=1; i<=n; ++i) cin>>a[i]>>b[i];
	return;
}
void Solve(){
	Read();
	ans=A=res=0;
	while(!q.empty()) q.pop();
	for(int i=1; i<=n; ++i){
		A+=a[i]; res+=a[i]; ans=max(ans,res);
		q.push(b[i]); A-=b[i];
		while(!q.empty()&&A<0){
			int u=q.top(); A+=q.top()-B;
			res-=B; q.pop();
		}
		if(res<0) break;
	}
	cout<<ans<<'\n';
	return;
}
signed main(){
	//freopen("test.in","r",stdin);
	//freopen("test.out","w",stdout);
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int T; cin>>T; while(T--) Solve();
	return 0;
}
posted @ 2025-11-21 17:19  BaiBaiShaFeng  阅读(7)  评论(0)    收藏  举报
Sakana Widget右下角定位