noi 2017 简要题解

本文回顾了noi 2017比赛,详细分析了第一天的整数问题,指出代码错误及调试过程,强调了细节和公式推导的重要性。第二天讨论了游戏、蔬菜和分身术问题,提到了2-SAT解决方法,并总结了做题技巧和教训,如充分理解题目、避免常数优化的误区。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

回顾noi 2017
DAY1
整数

压位维护序列。用线段树维护一段0后第一个1,一段A-1后第一个<(A - 1)的数
推推转移式子即可

代码犯了无数个错误,并且检查的时候没有仔细的检查出来,仍然借助gdb和对拍才调出来!非常糟糕!

**1. 线段树初始化错误
**2. 打错变量名3处
3. 进位后写成减M,应该是M+1
4. 很多地方一开始想清楚,改的时候没有想清楚,反而改错。比如二分是找最低位非满或非0.修改的时候一定要想清楚,很多时候找到错误反而没有全面的修改,浪费了更多时间
写代码前细节在头脑中不清晰,代码写得太少了!

#include<bits/stdc++.h>
using namespace std;
#define maxn 1002020
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define rvc(i,S) for(register int i = 0 ; i < (int)S.size() ; i++)
#define rvcd(i,S) for(register int i = ((int)S.size()) - 1 ; i >= 0 ; i--)
#define fore(i,x)for (register int i = head[x] ; i ; i = e[i].next)
#define pb push_back
#define prev prev_
#define stack stack_
#define mp make_pair
#define fi first
#define se second
#define inf 0x3f3f3f3f
typedef long long ll;
typedef pair<int,int> pr;

const ll M = (1 << 30) - 1,K = 30;
int cov[maxn << 2],tag[maxn << 2],val[maxn << 2];
// 1 : 全为M
// 2 :全为 0
// 0 :无性质
int n,t1,t2,t3,L;

void build(int x,int l,int r){
	tag[x] = 2 , cov[x] = -1;
	if ( l == r ) return;
	int mid = (l + r) >> 1;
	build(x << 1,l,mid) , build((x << 1) | 1,mid + 1,r);	
}
inline void cover(int x,int d){
	cov[x] = d , val[x] = d;
	if ( d == M ) tag[x] = 1;
	else tag[x] = 2;
}
inline void pushdown(int x){
	int ls = x << 1,rs = (x << 1) | 1;
	if ( cov[x] != -1 ){
		cover(ls,cov[x]);
		cover(rs,cov[x]);
		cov[x] = -1;
	}
}
inline void update(int x){
	int ls = x << 1,rs = (x << 1) | 1;
	if ( tag[ls] == 1 && tag[rs] == 1 ) tag[x] = 1;
	else if ( tag[ls] == 2 && tag[rs] == 2 ) tag[x] = 2;
	else tag[x] = 0;
}
void modify(int x,int l,int r,int L,int R,int d){
	if ( L > R ) return;
	if ( L <= l && R >= r ){
		cover(x,d);
		return;
	}
	int ls = x << 1,rs = (x << 1) | 1,mid = (l + r) >> 1;
	pushdown(x);
	if ( L <= mid ) modify(ls,l,mid,L,R,d);
	if ( R > mid ) modify(rs,mid + 1,r,L,R,d);
	update(x);
}
void modify(int x,int l,int r,int id,int d){
	if ( l == r ){
		val[x] += d;
		if ( val[x] == M ) tag[x] = 1;
		else if ( val[x] == 0 ) tag[x] = 2;
		else tag[x] = 0;
		return;
	}
	int ls = x << 1,rs = (x << 1) | 1,mid = (l + r) >> 1;
	pushdown(x);
	if ( id <= mid ) modify(ls,l,mid,id,d);
	else modify(rs,mid + 1,r,id,d);
	update(x);
}
int find1(int x,int l,int r,int L,int R){
	if ( tag[x] == 2 ) return 0;
	if ( l == r ) return l;
	int ls = x << 1,rs = (x << 1) | 1,mid = (l + r) >> 1;
	pushdown(x);
	if ( L <= l && R >= r ){
		if ( tag[ls] == 2 ) return find1(rs,mid + 1,r,L,R);
		return find1(ls,l,mid,L,R);
	}
	int p = 0;
	if ( L <= mid ) p = find1(ls,l,mid,L,R);
	if ( p ) return p;
	return find1(rs,mid + 1,r,L,R);
}
int find0(int x,int l,int r,int L,int R){
	if ( tag[x] == 1 ) return 0;
	if ( l == r ) return l;
	int ls = x << 1,rs = (x << 1) | 1,mid = (l + r) >> 1;
	pushdown(x);
	if ( L <= l && R >= r ){
		if ( tag[ls] == 1 ) return find0(rs,mid + 1,r,L,R);
		return find0(ls,l,mid,L,R);
	}
	i
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值