2018CCPC吉林赛区
A - The Fool
整除分块即可。
B - The World
模拟即可。
C - Justice
题意:
给出\(n\)个数\(k_i\),每个数的权值为\(\frac{1}{2^{k_i}}\)。
现在问能否将这些数划分为两个集合,使得每个集合里面数的权值和不小于\(\frac{1}{2}\)。
若合法,输出任意一种方案。
思路:
- 对于两个相同的\(k\),一定能够合并为\(k-1\)。
- 直接数组存储显然存不下,我们可以直接合并到\(k-x\),满足\(k-x\)存在,也就是说我们每次将\(a_i\)减小到\(a_{i-1}\),时间复杂度最多为\(O(logn)\)。
- 模拟这个过程就行了,后面输出方案的时候找到一个阀值即可。
说起来感觉比较简单,写起来没那么简单,细节很多。。后面寻找方案的时候也套了个二分(可能我姿势水平太低了)。
Code
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
// #define Local
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 5;
int n;
pii a[N], b[N], c[N];
int Case;
int bel[N], ans[N];
bool ok(int x, int y) {
	while(x != 1 && y >= 2) {
		--x; y /= 2;
	}
	if(x == 1) return true;
	return false;
}
void run() {
	++Case;
	cin >> n;
	for(int i = 1; i <= n; i++) {
		cin >> a[i].fi;
		a[i].se = i;
		bel[i] = ans[i] = 0;
	}
	sort(a + 1, a + n + 1);
	int tot = 0;
	for(int i = 1, j; i <= n; i = j) {
		j = i;
		while(j <= n && a[i].fi == a[j].fi) ++j;
		b[++tot] = MP(a[i].fi, j - i);
		for(int k = i; k < j; k++) bel[k] = tot;
	}
	b[0] = MP(1, 0);
	for(int i = 0; i <= tot; i++) c[i] = b[i];
	for(int i = tot; i > 0; i--) {
		int x = b[i].se;
		int now = b[i].fi, pre = b[i - 1].fi;
		while(now != pre && x >= 2) {
			x /= 2;
			--now;
		}
		if(now == pre) b[i - 1].se += x;
	}
	cout << "Case " << Case << ": ";
	if(b[0].se >= 2) {
		cout << "YES" << '\n';
	} else {
		cout << "NO" << '\n';
		return;
	}
	if(a[1].fi == 1) {
		ans[a[1].se] = 1;
		for(int i = 1; i <= n; i++) {
			cout << ans[i];
		}
		cout << '\n';
		return;
	}
	int need = 0, t = 0;
	for(int i = tot; i > 0; i--) {
		int x = c[i].se;
		int now = c[i].fi, pre = c[i - 1].fi;
		if(ok(now, x)) {
			int l = 1, r = x + 1, mid;
			while(l < r) {
				mid = (l + r) >> 1;
				if(ok(now, mid)) r = mid;
				else l = mid + 1;
			}
			t = tot + 1, need = r; break;
		}
		while(now != pre && x >= 2) {
			x /= 2;
			--now;
		}
		if(now != pre) x = 0;
		int k1 = c[i - 1].fi, k2 = c[i - 1].se + x;
		if(ok(k1, k2)) {
			int l = x, r = k2 + 1, mid;
			while(l < r) {
				mid = (l + r) >> 1;
				if(ok(k1, mid)) r = mid;
				else l = mid + 1;
			}
  			need = r - x; t = i; break;
		}
		c[i - 1].se += x;
	}
	for(int i = 1; i <= n; i++) {
		if(bel[i] >= t) {
			ans[a[i].se] = 1;
		} else if(bel[i] == t - 1 && need) {
			ans[a[i].se] = 1; --need;
		} else ans[a[i].se] = 0;
	}
	for(int i = 1; i <= n; i++) {
		cout << ans[i];
	}
	cout << '\n';
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
#ifdef Local
    freopen("../input.in", "r", stdin);
    freopen("../output.out", "w", stdout);
#endif
    int T; cin >> T;
    while(T--) run();
    return 0;
}
 
有一种更加简单优美的做法:并查集+优先队列。
并查集就维护合并路径,还是比较巧妙。
细节见代码:
Code
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
// #define Local
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 5;
int n;
int a[N];
int Case;
int f[N];
int find(int x) {
	return f[x] == x ? f[x] : f[x] = find(f[x]);
}
void run() {
	cout << "Case " << ++Case << ": ";
	cin >> n;
	for(int i = 1; i <= n; i++) cin >> a[i];
	for(int i = 0; i <= n; i++) {
		f[i] = i;
	}
	priority_queue <pii> q;
	for(int i = 1; i <= n; i++) {
		q.push(pii(a[i], i));
	}
	while(!q.empty() && q.top().fi > 1) {
		pii now = q.top(); q.pop();
		if(q.empty()) break;
		if(now.fi != q.top().fi) continue;
		pii cur = q.top(); q.pop();
		int fx = find(now.se), fy = find(cur.se);
		if(fx < fy) swap(fx, fy);
		f[fx] = fy;
		q.push(pii(now.fi - 1, fy));
	}
	if(q.size() <= 1) {
		cout << "NO" << '\n';
	} else {
		cout << "YES" << '\n';
		for(int i = 1; i <= n; i++) {
			if(find(i) == q.top().se) cout << 1;
			else cout << 0;
		}
		cout << '\n';
	}
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
#ifdef Local
    freopen("../input.in", "r", stdin);
    freopen("../output.out", "w", stdout);
#endif
    int T; cin >> T;
    while(T--) run();
    return 0;
}
D - The Moon
数学期望,就考虑几种情况就行,倒着来推,递推式详见代码:(因为有\(1.5\%\),所以是千分位)
Code
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int MAXN = 1e3+5;
typedef double db;
int t,p;
db f[MAXN];
db g(int x){
    return f[min(x,1000)];
}
int main() {
    scanf("%d",&t);
    for(int kase=1;kase<=t;kase++){
        scanf("%d",&p);
        f[1000] = 100.0/p;
        for(int i=995;i>=20;i-=5)
            f[i] = (p/100.0)*(i/1000.0) + (p/100.0)*((1000-i)/1000.0)*(1+g(i+20)) + (100-p)/100.0*(1+g(i+15));
        printf("Case %d: %.7f\n",kase,f[20]);
    }
    return 0;
}
F - The Hermit
仔细分析一下题目条件就很好做了,每一个位置答案为\(a_i-2\)。
H - Lovers
题意:
一开始有\(n\)个空串\(s_1,s_2,\cdots,s_n\),然后执行\(m\)次操作,操作分为两种:
- \(w\ l\ r\ d:\)给\(l\)到\(r\)位置上的所有子串两边加上\(d\),相当于\(s_i\)变为\(ds_id,l\leq i\leq r\);
- \(q\ l\ r:\)询问\(\sum_{i=l}^r value*(s_i)(mod\ 10^9+7)\)。
思路:
硬核线段树。
考虑若对一个位置施加一次操作,结果为:
\]
其中\(sum\)表示对应区间的答案和,\(sum_2\)表示对应区间的\(\sum 10^{len_i}\)。
三个的含义分别是头、中、尾部。
手玩一下,发现如果施加三次操作,结果将变为:
\]
那么我们可以发现,我们维护懒标记时,可以单独维护\([d_1\cdots d_n],[d_n\cdots d_1],10^{len}\),这样懒标记的更新也很好更新,懒标记下传时直接对应乘起来即可。
其中\([d_1d_2\cdots d_n]\)表示\(value(d_1d_2\cdots d_n)\)。
一开始细节没有想清楚,感觉还是有点遗憾。
注意一下\(sum_2\)的更新。
详见代码:
Code
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
// #define Local
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5 + 5, MOD = 1e9 + 7;
int Case;
int n, m;
int sum[N << 2], sum2[N << 2];
int llz[N << 2], rlz[N << 2], lenlz[N << 2];
char s[10];
void push_up(int o) {
	sum[o] = (sum[o << 1] + sum[o << 1|1]) % MOD;
	sum2[o] = (sum2[o << 1] + sum2[o << 1|1]) % MOD;
}
void upd(int son, int fa, int l, int r) {
	sum[son] = (1ll * lenlz[fa] * sum2[son] % MOD * llz[fa] % MOD +
				1ll * lenlz[fa] * sum[son] % MOD +
				1ll * rlz[fa] * (r - l + 1) % MOD) % MOD;
	sum2[son] = 1ll * lenlz[fa] * lenlz[fa] % MOD * sum2[son] % MOD;
	llz[son] = (1ll * llz[fa] * lenlz[son] % MOD + llz[son]) % MOD;
	rlz[son] = (1ll * rlz[son] * lenlz[fa] % MOD + rlz[fa]) % MOD;
	lenlz[son] = 1ll * lenlz[son] * lenlz[fa] % MOD;
}
void push_down(int o, int l, int r) {
	if(lenlz[o] > 1) {
		int mid = (l + r) >> 1;
		upd(o << 1, o, l, mid);
		upd(o << 1|1, o, mid + 1, r);
		lenlz[o] = 1;
		llz[o] = rlz[o] = 0;
	}
}
void build(int o, int l, int r) {
	llz[o] = rlz[o] = 0;
	lenlz[o] = 1;
	if(l == r) {
		sum[o] = 0; sum2[o] = 1;
		return;
	}
	int mid = (l + r) >> 1;
	build(o << 1, l, mid);
	build(o << 1|1, mid + 1, r);
	push_up(o);
}
void update(int o, int l, int r, int L, int R, int d) {
	if(L <= l && r <= R) {
		sum[o] = (1ll * sum[o] * 10 % MOD + 1ll * d * (r - l + 1) % MOD + 1ll * 10 * d * sum2[o] % MOD) % MOD;
		sum2[o] = 1ll * sum2[o] * 100 % MOD;
		llz[o] = (1ll * lenlz[o] * d % MOD + llz[o]) % MOD;
		rlz[o] = (1ll * rlz[o] * 10 + d) % MOD;
		lenlz[o] = 1ll * lenlz[o] * 10 % MOD;
		return;
	}
	push_down(o, l, r);
	int mid = (l + r) >> 1;
	if(L <= mid) update(o << 1, l, mid, L, R, d);
	if(R > mid) update(o << 1|1, mid + 1, r, L, R, d);
	push_up(o);
}
int query(int o, int l, int r, int L, int R) {
	if(L <= l && r <= R) {
		return sum[o];
	}
	push_down(o, l, r);
	int mid = (l + r) >> 1, res = 0;
	if(L <= mid) res = (res + query(o << 1, l, mid, L, R)) % MOD;
	if(R > mid) res = (res + query(o << 1|1, mid + 1, r, L, R)) % MOD;
	return res;
}
void run() {
	++Case;
	cout << "Case " << Case << ":" << '\n';
	cin >> n >> m;
	build(1, 1, n);
	while(m--) {
		cin >> s;
		int l, r, d;
		if(s[0] == 'w') {
			cin >> l >> r >> d;
			update(1, 1, n, l, r, d);
		} else {
			cin >> l >> r;
			int ans = query(1, 1, n, l, r);
			cout << ans << '\n';
		}
	}
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
#ifdef Local
    freopen("../input.in", "r", stdin);
    freopen("../output.out", "w", stdout);
#endif
    int T; cin >> T;
    while(T--) run();
    return 0;
}
I - Strength
游戏王,憨憨贪心,分两种情况就行。
Code
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
// #define Local
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int MAXN = 1e5+5;
int t,n,m,a[MAXN],b[MAXN],c[MAXN];
multiset<int> st;
bool vis[MAXN];
int main(){
    cin>>t;
    for(int kase=1;kase<=t;kase++){
        cin>>n>>m;
        for(int i=1;i<=n;i++)vis[i]=0;
        st.clear();
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=m;i++)cin>>b[i];
        int k=0;
        for(int i=1;i<=m;i++){
            int x;
            cin>>x;
            if(x==1)st.insert(b[i]);
            else c[++k] = b[i];
        }
        sort(a+1,a+1+n);
        sort(c+1,c+1+k);
        ll ans=0;
        for(int i=1;i<=n;i++){
            auto it = st.lower_bound(a[i]);
            if(*it == a[i]){
                st.erase(it);
                vis[i]=1;
            }else if(it!=st.begin()){
                it--;
                st.erase(it);
                vis[i]=1;
            }
        }
        ll sum = 0;
        if(st.size()==0){
            int j=1;
            for(int i=n;i>=1;i--){
                if(vis[i])continue;
                if(j<=k)sum += max(0,a[i] - c[j++]);
                else sum += a[i];
            }
        }
        ans = sum;
        int j=1;
        sum=0;
        for(int i=n;i>=1&&j<=k;i--){
            sum += max(0,a[i]-c[j++]);
        }
        ans=max(ans,sum);
        cout<<"Case "<<kase<<": "<<ans<<'\n';
    }
    return 0;
}
2018CCPC吉林赛区的更多相关文章
- 2018CCPC吉林赛区 hdu6555~hdu6566
		2018CCPC吉林赛区(重现赛)- 感谢北华大学 A 基础数论. #include<bits/stdc++.h> using namespace std; typedef long lo ... 
- [2018CCPC吉林赛区(重现赛)- 感谢北华大学] 补题记录 躁起来
		1007 High Priestess 埃及分数 1008 Lovers 线段树维护取膜意义下的区间s和. 每个区间保存前缀lazy和后缀lazy. #include <iostream> ... 
- 2018CCPC吉林赛区(重现赛)
		http://acm.hdu.edu.cn/contests/contest_show.php?cid=867 A题,直接分块,不知道正解是什么. #include<bits/stdc++.h& ... 
- 2018CCPC吉林赛区 | 部分题解  (HDU6555 HDU6556 HDU6559 HDU6561)
		// 杭电上的重现赛:http://acm.hdu.edu.cn/contests/contest_show.php?cid=867 // 杭电6555~6566可交题 A - The Fool 题目 ... 
- 2018CCPC吉林赛区(重现赛)部分题解
		The Fool 题目链接 Problem Description The Fool is numbered 0 – the number of unlimited potential –and th ... 
- 2018CCPC 吉林现场赛  赛后总结
		一直以来都没有比赛完写总结的习惯,导致前面几次比赛都没有写过总结. 这是我写的第一场总结把,有时间有想法还记得细节的话再把前面几次比赛的总结给补上把. 热身赛: 热身赛的时候,写的比较急想着快点做出题 ... 
- HDU 6556 (2018CCPC吉林 B题)
		### HDU 6556 题目链接 ### 题目大意: 给你四个国家的时区,告诉你 A 国家的时间,让你输出这时候在 B 国家的时间,还需要输出对于 A 国家来说这是 昨天.今天 还是 明天. 分析前 ... 
- 2018ccpc吉林 E:THE TOWER——数形结合
		题目 链接 给你一个圆锥(位于坐标原点,告诉你高h 和底面半径 r),和一个点(x,y,z)并告诉你这个点的速度, 让你求点和圆锥相撞的最小时间(保证一定相撞) 分析 易知,将直线的参数方程与圆锥曲面 ... 
- HDU 6562 lovers 2018CCPC吉林H(线段树)
		题意: 初始n个空串,m个操作: 1.给[l,r]的所有字符串头尾加一个‘d’,将原字符串x变为dxd 2.求[l,r]所有字符串代表的数字之和mod 1e9+7 思路: 据说是硬核线段树.. 对于线 ... 
随机推荐
- 一起学SpringMVC之RequestMapping详解
			本文以一个简单的小例子,简述SpringMVC开发中RequestMapping的相关应用,仅供学习分享使用,如有不足之处,还请指正. 什么是RequestMapping? RequestMappin ... 
- C# Replace字符替换函数
			它可以将字串内的字符替换为别的字符,可以嵌套使用,如下: 需要注意的是,它可以把字符替换为空,但不可以替换空字符,当不确定字符串是否为空时,可以进行以下判断,再替换: 示例的完整代码: string ... 
- SpringBoot"热"部署解决方案
			作者:故事我忘了¢个人微信公众号:程序猿的月光宝盒 SpringBoot热部署两种方式 1.SpringLoader 插件  缺点: Java 代码做部署处理.但是对页面无能为力. 2.DevToo ... 
- Flask 模板语言,装饰器
			Jinja2模板语言 # -*- coding: utf-8 -*- from flask import Flask, render_template, request, redirect, ... 
- 天下代码一大抄,整个案例的搬是什么鬼!疑似冒充蚂蚁金服高级Java开发工程师?你大爷
			写在开始 上班前的第一件事,就是码云看看有什么消息,回复下网友的问题.如果看到喜欢的项目会点进去瞅瞅,然后就开始一天的工作. 然而,这一天的工作并不开心,一个今日热门项目让自己很恼火,一开始感觉并没有 ... 
- JDK 安装与环境配置配置——Android开发第一步
			什么是JDK? JDK 即 Java Development Kit,Java开发工具包,用来编译 Java 程序.JRE 在接触JDK的过程中,同时了解到 JRE,JRE 即 Java Runtim ... 
- 一文彻底搞清楚 Material Design
			一文彻底搞清楚 Material Design 首先声明以下介绍的关于 Material Design 的介绍,都是基于在 Android 环境下,其实 Material Design 是一种为了让 ... 
- 微信小程序框架部署:mpvue+typescript
			开发前提: 1.在微信公众平台注册申请 AppID 2.安装开发者工具https://developers.weixin.qq.com/miniprogram/dev/devtools/downloa ... 
- python科学计算和数据分析常用库
			NumPy NumPy最强大的是n维数组,该库还包含基本的线性代数函数.傅立叶变换.随机函数和其他底层语言(如Fortran.C和C++)集成的工具. SciPy SciPy建立在NumPy基础上,它 ... 
- 原生js放大镜效果
			效果: 1. 鼠标放上去会有半透明遮罩.右边会有大图片局部图 2. 鼠标移动时右边的大图片也会局部移动 放大镜的关键原理: 鼠标在小图片上移动时,通过捕捉鼠标在小图片上的位置,定位大图片的相应位置 ... 
