首页 > 其他分享 >$20240119$ 练习题解

$20240119$ 练习题解

时间:2024-01-19 20:33:59浏览次数:28  
标签:练习题 tmp ok nxt int cin 20240119 dis

\(20240119\) 练习题解

CF472D

通过尝试我们容易发现,与点 \(1\) 最近的点一定是直接儿子。我们要是把它作为突破点,那就成功了一半了。

假设点 \(2\) 与点 \(1\) 最近,又假设我们可以用函数 \(F(x)\) 来确定 \(x\) 点的子树形态。那我们会发现如果我们还有剩余的节点,那么剩余的节点中与 \(1\) 最近的也是它儿子,这样反复就能确定该树。所以我们要尝试思考该函数。

我们发现 \(F(x)\) 的目的好像也可以用“找最近的儿子”方法解决,但是新的困难是:我们可能还会有子树外的点。我们只需确定某点 \(y\) 是否在子树 \(x\) 内 \((x > 1)\)。设 \(x\) 的父节点为 \(fa\)。那么:

  • 若是,则有 \(dis_{fa, y}-dis_{x, y}=dis_{fa, x}\);
  • 否则,有 \(dis_{fa, y}-dis_{x, y}=-dis_{fa, x}\)。

于是就解决了。

#include <bits/stdc++.h>
using namespace std;
const int N = 2e3 + 5;
int ok[N], n, a[N][N], fa[N];
bool dfs(int u, int pre){
	ok[u] = 1;
	while(1){	
		int Min = INT_MAX, tmp = 0;
		for(int i = 1; i <= n; i++){
			if(abs(a[pre][i] - a[u][i]) != a[pre][u]) return 1;
			if(!ok[i] && a[pre][i] - a[u][i] == a[pre][u] && Min > a[u][i]) Min = a[u][i], tmp = i;
		}
		if(!tmp) break;
		fa[tmp] = u;
		if(dfs(tmp, u)){
			return 1;
		}
	}
	return 0;
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	cin >> n;
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= n; j++){
			cin >> a[i][j];
			if(i == j && a[i][j]){
				cout << "NO" << endl;
				return 0;
			}
			if(i != j && !a[i][j]){
				cout << "NO" << endl;
				return 0;
			}
			if(i > j && a[i][j] != a[j][i]){
				cout << "NO" << endl;
				return 0;
			}
		}
	}
	ok[1] = 1;
	int cnt = 0;
	while(1){
		cnt++;	
		int Min = INT_MAX, tmp = 0;
		for(int i = 1; i <= n; i++){
			if(!ok[i] && Min > a[1][i]) Min = a[1][i], tmp = i;
		}
		if(!tmp) break;
		fa[tmp] = 1;
		if(dfs(tmp, 1)){
			cout << "NO" << endl;
			return 0;
		}
		if(cnt == n + 5){
			cout << "NO" << endl;
			return 0;
		}
	}
	cout << "YES" << endl;
	return 0;
}

CF500E

题意太过复杂,大致为:给定 \(n\) 个区间,每次询问第 \(l\) 个区间的左端到第 \(r\) 个的右端中有几个单位长度未被覆盖

pic 1

如图,记录:

  • \(nxt_i\) 为向右推到 \(i\) 号骨牌后 \(i\) 右侧第一个没倒的,如图 \(nxt_{\text{红}}=\text{黄}\);
  • \(f_i\) 为向右推到后的能到达的最大位置,例如 \(f_{\text{红}}=D\);
  • \(val_i\) 为空缺的单位长度,如 \(val_{\text{红}}=DE=1\)。

接着就倍增就好了。

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n, q, p[N], l[N], f[N], nxt[N][25], val[N][25];
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	cin >> n;
	for(int i = 1; i <= n; i++)
		cin >> p[i] >> l[i];
	p[n + 1] = INT_MAX;
	nxt[n][0] = n + 1, f[n] = p[n] + l[n];
	for(int i = n - 1; i >= 1; i--){
		nxt[i][0] = i + 1;
		f[i] = p[i] + l[i];
		while(p[i] + l[i] >= p[nxt[i][0]]) f[i] = max(f[i], f[nxt[i][0]]), nxt[i][0] = nxt[nxt[i][0]][0];
	}
	for(int i = n; i >= 1; i--){
		if(nxt[i][0] == n + 1) continue;
		val[i][0] = p[nxt[i][0]] - f[i];
	}
	nxt[n + 1][0] = n + 1;
	for(int i = 1; i <= 20; i++){
		for(int j = n; j >= 1; j--){
			nxt[j][i] = nxt[nxt[j][i - 1]][i - 1];
			val[j][i] = val[j][i - 1] + val[nxt[j][i - 1]][i - 1];
		}
		nxt[n + 1][i] = n + 1;
	}
	cin >> q;
	int ans = 0, l, r;
	while(q--){
		ans = 0;
		cin >> l >> r;
		for(int i = 20; i >= 0; i--)
			if(nxt[l][i] <= r)
				ans += val[l][i], l = nxt[l][i];
		cout << ans << endl;
	}
	return 0;
}

CF241E

蛮好,抽象的。

发现一条边只能是 \(1\) 或 \(2\),然后:

\[\begin{cases} ddis_v \le dis_u + 2\\ dis_u \le dis_v − 1 \end{cases} \]

直接差分约束。

确实蛮好。

#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
const int N = 1e6;
int cnt, a[N], b[N], c[N], n, m, dis[N], ok[N], used[N];
int s1[N], s2[N];
vector<int> g[N];
void addEdge(int x, int y, int z){
	cnt++, a[cnt] = x, b[cnt] = y, c[cnt] = z;
	return ;
}
void dfs(int u){
	used[u] = 1;
	if(u == n){
		ok[u] = 1;
		return ;
	}
	for(int v : g[u]){
		if(used[v]){
			ok[u] |= ok[v];
			continue;
		}
		dfs(v);
		ok[u] |= ok[v];
	}
	return ;
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	cin >> n >> m;
	for(int i = 1; i <= m; i++){
		int x, y;
		cin >> x >> y;
		g[x].push_back(y);
		s1[i] = x, s2[i] = y;
	}
	dfs(1);
	for(int i = 1; i <= m; i++)
		if(ok[s1[i]] && ok[s2[i]])
			addEdge(s1[i], s2[i], 2), addEdge(s2[i], s1[i], -1);
	for(int i = 1; i <= n; i++) dis[i] = 1e9;
	dis[1] = 0;
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= cnt; j++){
			dis[b[j]] = min(dis[b[j]], dis[a[j]] + c[j]);
		}
	}
	for(int i = 1; i <= cnt; i++){
		if(dis[b[i]] > dis[a[i]] + c[i]){
			cout << "No" << endl;
			return 0;
		}
	}
	cout << "Yes" << endl;
	for(int i = 1; i <= m; i++){
		if(ok[s1[i]] && ok[s2[i]])
			cout << dis[s2[i]] - dis[s1[i]] << endl;
		else
			cout << 2 << endl;
	}
	return 0;
}

CF41D

更抽象了,因为随机,所以直接暴力 \(1\) 到 \(24\) 的数,代码不放了。

标签:练习题,tmp,ok,nxt,int,cin,20240119,dis
From: https://www.cnblogs.com/lc0802/p/17975536

相关文章

  • 20240119
    卡常狗能不能死一死啊A.构造87bitset瞎搞#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#defineullunsignedlonglong#defineALL(a)(a).begin(),(a).end()#definepbpush_back#definemkmake_pair#definepiipair<int,int>#define......
  • 练习题1
    使用面向对象的思想,编写自定义描述狗的信息。设定属性包括:品种,年龄,心情,名字;方法包括:叫,跑。要求:1)设置属性的私有访问权限,通过公有的get,set方法实现对属性的访问2)限定心情只能有“心情好”和“心情不好”两种情况,如果无效输入进行提示,默认设置“心情好”。3)设置构造......
  • PA0:关于练习题
    练习11: 附加题:复制操作:i=0;while(i<argc){states[i]=argv[i];i++;}如果还要考虑安全性,那就在循环体里面增加判断:i=0;j=0;while(i<argc){states[i]=argv[i];i++;j++;if(j>=......
  • PA0:关于练习题
    网页浏览体验很差,希望下次不要再找广告满天飞的网站搭翻译博客。网页做的很好,以后别做了。  不使用stdio库。gcc在make时会提示存在implicitdeclaration(隐式声明)--------------------------------------------makefile基本指令解释:CFLAGS=-Wall-g clean:   rm......
  • 算法练习题-系列一
    目录柯里化实现柯里化函数柯里化函数作用扁平化[双指针]有序数组合并判断一个字符串是否是回文字符串[字符串]两个版本号version1和version2[字符串]版本号大小比较排序['1.45.0','1.5','6','3.3.3.3.3.3.3']=>['1.5','1.45.0','3.3.3.3.3.3','6']给定两个......
  • 队列练习题
    求m区间内的最小值(洛谷P1440)题目大意对一序列a,从左至右扫描,取每个位置前m个数的最小值,位置为首位置时输出0,不足m个数时就取这段范围内的最小值。解题思路使用单调队列,保持队头存最小元素下标,从队尾更新最值,超出窗口范围时队头出队。未知的代码#include<bits/stdc++.h>u......
  • 栈练习题
    单调栈(洛谷P5788)题目大意与栈中的向右看齐相同题解未知的代码#include<bits/stdc++.h>usingnamespacestd;constintN=3e6+5;inta[N],ans[N],n;stack<int>s;intmain(){cin>>n;for(inti=1;i<=n;i++)cin>>a[i];for(inti=n;i>=1;i--){......
  • Java多线程​(五)练习题7道
    练习多线程练习1(卖电影票)一共有1000张电影票,可以在两个窗口领取,假设每次领取的时间为3000毫秒,要求:请用多线程模拟卖票过程并打印剩余电影票的数量线程类实现:publicclassTicketWindowextendsThread{publicTicketWindow(){}publicTicketWindow(Stringname){super(nam......
  • c203数据库练习题下半
    2、视图练习(1)建立视图v_xs_1,要求包含男生的学号,姓名,性别,出生日期,班级编号,专业名称字段,并要求视图操作数据时进行检查。使用select命令查询创建的视图。createviewv_xs_1asselectxh,xm,xb,csrq,bjbh,zymcfromxsjbxxbwherexb='男'withcheckoption;建立一个学院教师......
  • c203数据库练习题上半
    1.使用SQL语言创建满足以下要求的数据库。(1)创建数据库名称为jwgl,字符集选择utf8,排序规则选择utf8_general_ci。createdatabasejwglcharactersetutf8collateutf8_general_ci;(2)查看数据库。showdatabases;(3)将数据库jwgl的指定字符集修改为gb2312。mysql>alterdatabasejwg......