首页 > 其他分享 >CSP-S开小灶1

CSP-S开小灶1

时间:2022-09-05 19:12:37浏览次数:60  
标签:int mi t2 t1 ans 开小灶 include CSP

A. ZZH的游戏

假设我们知道答案 \(ans\)

我们每次要在两棵树上尝试走到编号尽可能小的点,这样我们能走到的范围单调递增

二分答案会多个 \(log\), 我们考虑另一种方法

初始\(ans = s + t\)

然后两棵树扩展到不能动为止,这个时候我们让 \(ans++\),继续之前的过程,直到两棵树都到 \(1\)为止

具体过程可以用桶排优化到线性,但是我太菜了,只会优先队列多个\(log\)

upd:其实完全没有排序,直接每次对之前不能访问但能到达的最小的\(dfs\)下去就行了,写成我这样的\(bfs\)就是完全的负优化

code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;

int read(){
	int x = 0; char c = getchar();
	while(c < '0' || c > '9')c = getchar();
	do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
	return x;
}
const int maxn = 1000005;
int n;
struct tree{
	struct edge{
		int to, net;
	}e[maxn << 1 | 1];
	int head[maxn], tot;
	void add(int u, int v){
		e[++tot].net = head[u];
		head[u] = tot;
		e[tot].to = v;
	}
	bool vis[maxn];
	int mi = maxn + maxn + maxn;
	priority_queue<int, vector<int>, greater<int> >q;
	void clear(){
		for(int i = 1; i <= n; ++i)head[i] = 0;
		for(int i = 1; i <= n; ++i)vis[i] = 0;
		tot = 0; mi = maxn + maxn + maxn;
		while(!q.empty())q.pop();
	}
	void built(){
		for(int i = 1; i < n; ++i){
			int u = read(), v = read();
			add(u, v); add(v, u);
		}
	}
	bool expand(int mx){
		bool flag = 0;
		while(!q.empty()){
			int x = q.top();
			if(x > mx)break;
			q.pop(); vis[x] = 1; flag = 1; mi = min(mi, x);
			for(int i = head[x]; i; i = e[i].net){
				int v = e[i].to; if(vis[v])continue;
				q.push(v);
			}

		}
		return flag;
	}
	void set(int x){mi = x; q.push(x);}
}t1, t2;
int s, t;
int solve(){
	n = read(); t1.built(); t2.built();
	s = read(); t = read();
	int ans = s + t;
	t1.set(s); t2.set(t);
	t1.expand(s); t2.expand(t);
	while(1){
		bool f1 = 1, f2 = 1;
		while(f1 || f2){
			if(t1.mi == 1 && t2.mi == 1)return ans;
			f1 = t1.expand(ans - t2.mi);
			f2 = t2.expand(ans - t1.mi);
		}
		++ans;
	}
}
int main(){
	int t = read();
	for(int ask = 1; ask <= t; ++ask){
		printf("%d\n",solve());
		t1.clear(); t2.clear();
	}
	return 0;
}

B. ZZH与背包

考场打了个搜索 + 剪枝,大样例没跑过, 交上去切了 ???

正解不是很理解,但是有近似正解的做法

分成两组,\(\text{meet in middle}\)

左半边枚举,右半边双指针

code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<map>
#include<set>

using namespace std;

typedef long long ll;
ll read(){
	ll x = 0; char c = getchar();
	while(c < '0' || c > '9')c = getchar();
	do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
	return x;
}
int n, q, v[45], m1, m2, n1, n2;
ll a[(1 << 20) + 5], b[(1 << 20) + 5];
ll solve(ll mv){
	ll ans = 0; int r = 0;
	for(int l = m1 - 1; l >= 0; --l){
		while(r < m2 && a[l] + b[r] <= mv) ++r;
		ans += r;
	}
	return ans;
}
int lg[(1 << 20) + 5];
int main(){
	n = read(), q = read();
	n1 = n / 2, n2 = n - n1;
	for(int i = 1; i <= n1; ++i)v[i] = read();
	m1 = 1 << n1;
	lg[1] = 0;
	for(int i = 1; i <= n2; ++i)lg[1 << i] = i; 
	for(register int i = 0; i < m1; ++i){
		int now = i;
		for(register int j = now; j; j -= j & -j)a[i] += v[lg[j & -j] + 1];
	}
	sort(a + 1, a + m1);
	for(int i = 1; i <= n2; ++i)v[i] = read();
	m2 = 1 << n2;
	for(register int i = 0; i < m2; ++i){
		int now = i;
		for(register int j = now; j; j -= j & -j)b[i] += v[lg[j & -j] + 1];
	}
	sort(b + 1, b + m2);
	for(int i = 1; i <= q; ++i){
		ll l = read(), r = read();
		printf("%lld\n",solve(r) - solve(l - 1));
	}
	return 0;
}

标签:int,mi,t2,t1,ans,开小灶,include,CSP
From: https://www.cnblogs.com/Chencgy/p/16659236.html

相关文章

  • 青少年C++编程CSP/NOIP
    C++基础篇C++算法篇数据结构&算法深入信息学竞赛初赛篇信息学竞赛复赛篇信息学等级考试篇C++提高篇https://study.163.com/series/1202896601.htm?inLoc=android_ss_ssjg&u......
  • CSP-S模拟2
    本来我不怎么写题解的,但这次考试收获挺大,就写写T1.求\(Des(a,b)=n\)因为\(Des(a,b)=\Theta(a^b)\)所以可以利用这个性质快速找到\(a\)附近的数多次开根号即......
  • CSP-S模拟2(联考)
    差点又双叒叕模拟退役上来先\(\%T2\),然后感觉就差一点,最后搞出来就十点多了..然后心态一度爆炸,有点小摆烂,上厕所冷静一下觉得还有时间,能抢救一下然后开了\(T1\),没......
  • CSP-S模拟2(联考) 谜之阶乘 子集 混凝土粉末 排水系统
    rank4040多分?T1:暴力;T2:构造T2:构造出(1--n)的连续整数分成k组,每组的数加起来一样。(n<=1e6)只要能实现一种构造方案,使得3k个连续数字分k组可以达到(a+b+c)相同(或2k,很显然......
  • CSP-S模拟1 [斐波那契,数颜色,分组]
    CSP-S模拟1洛谷上原题,不挂题面了。A.斐波那契P3938斐波那契观察上图,可发现规律:一个数的父亲等于这个数减去最大的小于它的斐波那契数。特殊的,如果这个数是斐波那契......
  • CSP-S加赛1
    A.antipalindrome真·签到题然后忘了给\(m\)取模,挂了\(10pts\)考虑任何大于\(1\)的回文,必然存在相邻两个字母相同,或者中间隔一个字母,那么从前往后考虑每一个位......
  • CSP-S模拟1
    下发文件和题解A.斐波那契对于上面这张图,尝试从2开始依次写下每个兔子的父亲的标号:那么转换成数列就是这样的:111212312345...可以发现这个序列由多个......
  • CCF CSP-J/S 2021第二轮获奖分数线及评级规则
    CCFNOI科学委员会、竞赛委员会召开会议,确定了CCFCSP-J/S2021第二轮评级规则及评级名额方案。提高级一等名额分配方案提高级一等全国认证基准线:100分CCFCSP-J/S第二......
  • CSP_202206-2_寻宝!大冒险!
    CSP_202206-2_寻宝!大冒险题目链接思路相当于判断两个有限集合AB之间是不是满射和单射,只需要保证以下两点A和B元素个数相等A中每个元素都能通过映射\(\psi\)到B中一个......
  • hzx的CSP-J模拟赛题解
    T1按题意模拟即可,注意不用考虑闰年。T2\(30\%\)的数据:使用\(Floyd\)求出图的全源最短路,时间复杂度\(O(n^3)\)。\(50\%\)的数据:对图上每个点使用\(Dijkstra\)求......