
Codeforces Round #703 (Div. 2) 题解
发布日期:2021-05-06 15:23:52
浏览次数:19
分类:精选文章
本文共 9644 字,大约阅读时间需要 32 分钟。
A - Shifting Stacks
最优情况是。
#includeusing namespace std ;int main(){ std::ios::sync_with_stdio(false) , cin.tie(0) ; int T ; cin >> T ; while(T --) { int n ; cin >> n ; vector a(n) ; for(int i = 0 ; i < n ; i ++) cin >> a[i] ; bool flag = true ; for(int i = 0 ; i < n ; i ++) { if(a[i] < i) { flag = false ; break ; } else { long long t = a[i] - i ; a[i] -= t ; if(i + 1 < n) a[i + 1] += t ; } } if(flag) cout << "YES\n" ; else cout << "NO\n" ; } return 0 ;}
B - Eastern Exhibition
一个经典结论就是最小化的
是
的中位数,如果
是偶数,那么
是中间的一段区间。
轴分别算再相乘即可。
#includeusing namespace std ;int main(){ std::ios::sync_with_stdio(false) , cin.tie(0) ; int T ; cin >> T ; while(T --) { int n ; cin >> n ; vector x(n) , y(n) ; for(int i = 0 ; i < n ; i ++) cin >> x[i] >> y[i] ; sort(x.begin() , x.end()) ; sort(y.begin() , y.end()) ; int cnt1 = x[n / 2] - x[(n - 1) / 2] + 1 ; int cnt2 = y[n / 2] - y[(n - 1) / 2] + 1 ; cout << 1ll * cnt1 * cnt2 << '\n' ; } return 0 ;}
C2 - Guessing the Greatest (hard version)
第一次询问: id=ask(1,n)。
第二次询问:m=ask(1,id-1)。可以知道最大值在[1,id-1]还是[id+1.n]。
剩下log次询问:假如最大值在id左侧,通过ask(m,id)=id找到最大的m就是答案。
#includeusing namespace std ;int ask(int l , int r){ printf("? %d %d\n" , l , r) ; fflush(stdout) ; int y ; scanf("%d" ,&y) ; return y ;}int main(){ int n ; scanf("%d" , &n) ; int id = ask(1 , n) ; int m ; if(id == 1) m = n ; else if(id == n) m = 1 ; else { if(ask(1 , id) == id) m = 1 ; else m = n ; } if(m < id) { int ll = 1 , rr = id - 1 ; while(ll <= rr) { int mid = (ll + rr) / 2 ; if(ask(mid , id) == id) m = mid , ll = mid + 1 ; else rr = mid - 1 ; } } else { int ll = id + 1 , rr = n ; while(ll <= rr) { int mid = (ll + rr) / 2 ; if(ask(id , mid) == id) m = mid , rr = mid - 1 ; else ll = mid + 1 ; } } printf("! %d\n" , m) ; fflush(stdout) ; return 0 ;}
D - Max Median
二分答案就好啦。check(x)的时候对于大于等于x的数就标记为1,其他数标记为-1。一段长度不小于k的连续子序列的和大于0,那么就合法。
#includeusing namespace std ;const int maxn = 2e5 + 10 ;int a[maxn] ;int mn[maxn << 2] ;int n , k ;int ls(int x){ return x << 1 ;}int rs(int x){ return x << 1 | 1 ;}void update(int id , int l , int r , int x , int y){ int mid = (l + r) / 2 ; if(l == r && l == x){mn[id] = y ; return ;} if(x <= mid) update(ls(id) , l , mid , x , y) ; else update(rs(id) , mid + 1 , r , x , y) ; mn[id] = min(mn[ls(id)] , mn[rs(id)]) ;}int query(int id , int l , int r , int x , int y){ int ans = 1e9 ; int mid = (l + r) / 2 ; if(y < x) return 0 ; if(x <= l && r <= y) return mn[id] ; if(x <= mid) ans = min(ans , query(ls(id) , l , mid , x , y)) ; if(y > mid) ans = min(ans , query(rs(id) , mid + 1 , r , x , y)) ; return ans ;}bool ok(int x){ int now = 0 ; memset(mn , 0x3f , sizeof(mn)) ; for(int i = 1 ; i <= n ; i ++) { if(a[i] >= x) now ++ ; else now -- ; update(1 , 1 , n , i , now) ; if(i >= k) { int t = query(1 , 1 , n , i , i) ; if(t > 0) { return true ; } if(i > k) { if(query(1 , 1 , n , 1 , i - k) < t) return true ; } } } return false ;}int main(){ std::ios::sync_with_stdio(false) , cin.tie(0) ; cin >> n >> k ; for(int i = 1 ; i <= n ; i ++) cin >> a[i] ; int ans = 1 ; int l = 1 , r = n ; while(l <= r) { int mid = (l + r) / 2 ; if(ok(mid)) ans = mid , l = mid + 1 ; else r = mid - 1 ; } cout << ans << '\n' ; return 0 ;}
E - Paired Payment
主要是建立一些虚点和虚边,然后跑一下dij。参考上图和代码。
#include#define pb push_back#define fi first#define se second#define sz(x) (int)x.size()#define cl(x) x.clear()#define all(x) x.begin() , x.end()#define rep(i , x , n) for(int i = x ; i <= n ; i ++)#define per(i , n , x) for(int i = n ; i >= x ; i --)#define mem0(x) memset(x , 0 , sizeof(x))#define mem_1(x) memset(x , -1 , sizeof(x))#define mem_inf(x) memset(x , 0x3f , sizeof(x))#define debug(x) cerr << #x << " = " << x << '\n'#define ddebug(x , y) cerr << #x << " = " << x << " " << #y << " = " << y << '\n'#define ios std::ios::sync_with_stdio(false) , cin.tie(0)using namespace std ;typedef long long ll ;typedef long double ld ;typedef pair pii ;typedef pair pll ;typedef double db ;const int mod = 998244353 ;const int maxn = 1e7 + 1e6 + 10 ;const int inf = 0x3f3f3f3f ;const double eps = 1e-6 ; typedef pair pli ; //��Ȩlong longstruct Link{ int num , head[maxn] ; struct Edge { int v , next ; int w ; } edge[maxn << 1] ; void init() { num = 0 ; memset(head , -1 , sizeof(head)) ; } void add(int u , int v , int w) { edge[num].v = v ; edge[num].w = w ; edge[num].next = head[u] ; head[u] = num ++ ; }} link ;struct Dij{ int dis[maxn] ; priority_queue , greater > q ; void init() { memset(dis , 0x3f , sizeof(dis)) ; } void dijkstra(int s) { dis[s] = 0 ; q.push(make_pair(0 , s)) ; while(!q.empty()) { pii p = q.top() ; q.pop() ; int u = p.second ; if(p.first != dis[u]) continue ; //�Ż������þ�ֵ���¡� for(int i = link.head[u] ; i != -1 ; i = link.edge[i].next) { int v = link.edge[i].v ; int w = link.edge[i].w ; if(dis[v] > dis[u] + w) { dis[v] = dis[u] + w ; q.push(make_pair(dis[v] , v)) ; } } } }} dij ;int main(){ ios ; link.init() ; dij.init() ; int n , m ; cin >> n >> m ; while(m --) { int u , v , w ; cin >> u >> v >> w ; u -- , v -- ; link.add(u * 51 , v * 51 + w , 0) ; for(int i = 1 ; i <= 50 ; i ++) link.add(u * 51 + i , v * 51 , (i + w) * (i + w)) ; swap(u , v) ; link.add(u * 51 , v * 51 + w , 0) ; for(int i = 1 ; i <= 50 ; i ++) link.add(u * 51 + i , v * 51 , (i + w) * (i + w)) ; } dij.dijkstra(0) ; for(int i = 0 ; i < n ; i ++) if(dij.dis[i * 51] > 1e9) dij.dis[i * 51] = -1 ; for(int i = 0 ; i < n ; i ++) cout << dij.dis[i * 51] << " \n"[i == n - 1] ; return 0 ;}
F - Pairs of Paths
总共就这三种情况。分类讨论即可。耐心写。
时间复杂度:。常数有点大。
可以去掉,但是时限很宽裕,不去掉好写一些。
#includeusing namespace std ;const int maxn = 3e5 + 10 ;int n , m ;vector g[maxn] ;int dep[maxn] , fa[maxn][25] ;int now ;int dfn[maxn] , sz[maxn] ;vector > s[maxn] ;int c[maxn] ; // c[u]表示一个端点在u子树内部,另一个端点在u子树外部map d[maxn] ;void dfs1(int f , int u , int deep){ dfn[u] = ++ now ; sz[u] = 1 ; dep[u] = deep ; for(int i = 1 ; i <= 20 ; i ++) { int nxt = fa[u][i - 1] ; fa[u][i] = fa[nxt][i - 1] ; } for(auto v : g[u]) { if(v == f) continue ; fa[v][0] = u ; dfs1(u , v , deep + 1) ; sz[u] += sz[v] ; s[u].push_back({dfn[v] , v}) ; }}int lca(int x , int y) { if(dep[x] < dep[y]) swap(x , y) ; for(int i = 20 ; i >= 0 ; i --) if(dep[fa[x][i]] >= dep[y]) x = fa[x][i] ; if(x == y) return x ; for(int i = 20 ; i >= 0 ; i --) if(fa[x][i] != fa[y][i]) x = fa[x][i] , y = fa[y][i] ; return fa[x][0] ;}vector > p[maxn] ;int cnt[maxn] ;int change(int lc , int u){ pair tt = {dfn[u] , 1000000000} ; auto it = upper_bound(s[lc].begin() , s[lc].end() , tt) ; it -- ; d[lc][(*it).second] ++ ; return (*it).second ;}long long cal1() //same lca{ long long res = 0 ; for(int i = 1 ; i <= n ; i ++) { int siz = p[i].size() ; sort(p[i].begin() , p[i].end()) ; res += 1ll * siz * (siz - 1) ; for(int j = 0 ; j < siz ; j ++) { if(p[i][j].first != -1) cnt[p[i][j].first] ++ ; if(p[i][j].second != -1) cnt[p[i][j].second] ++ ; } for(int j = 0 ; j < siz ; j ++) { int k = j ; while(k + 1 < siz && p[i][k + 1] == p[i][k]) k ++ ; for(int t = j ; t <= k ; t ++) { if(p[i][t].first == -1 && p[i][t].second == -1) continue ; else if(p[i][t].second == -1) { int num = cnt[p[i][t].first] - 1 ; res -= num ; } else { int num = cnt[p[i][t].first] - 1 ; num += cnt[p[i][t].second] - 1 ; num -= (k - j + 1) - 1 ; res -= num ; } } j = k ; } for(int j = 0 ; j < siz ; j ++) { if(p[i][j].first != -1) cnt[p[i][j].first] = 0 ; if(p[i][j].second != -1) cnt[p[i][j].second] = 0 ; } } return res / 2 ;}long long cal2(int fa , int u) //not same lca{ long long res = 0 ; for(auto v : g[u]) { if(v == fa) continue ; res += cal2(u , v) ; int res2 = c[v] - d[u][v] ; //一个端点在v子树内部,另一个端点在u子树外部。 c[u] += res2 ; int cc = p[u].size() - d[u][v] ; res += 1ll * res2 * cc ; } return res ;}int main(){ std::ios::sync_with_stdio(false) , cin.tie(0) ; cin >> n ; for(int i = 1 ; i <= n - 1 ; i ++) { int u , v ; cin >> u >> v ; g[u].push_back(v) ; g[v].push_back(u) ; } vector tmp ; dfs1(1 , 1 , 1) ; cin >> m ; for(int i = 1 ; i <= m ; i ++) { int u , v ; cin >> u >> v ; int lc = lca(u , v) ; if(u == v) p[u].push_back({-1 , -1}) ; else if(u == lc) { c[v] ++ ; tmp.push_back(v) ; p[lc].push_back({change(lc , v) , -1}) ; } else if(v == lc) { c[u] ++ ; tmp.push_back(u) ; p[lc].push_back({change(lc , u) , -1}) ; } else { c[u] ++ ; c[v] ++ ; tmp.push_back(u) ; tmp.push_back(v) ; int t1 = change(lc , u) ; int t2 = change(lc , v) ; p[lc].push_back({min(t1 , t2) , max(t1 , t2)}) ; } } long long ans = 0 ; ans += cal1() ; ans += cal2(1 , 1) ; for(auto u : tmp) ans += p[u].size() ; cout << ans << '\n' ; return 0 ;}
发表评论
最新留言
留言是一种美德,欢迎回访!
[***.207.175.100]2025年04月17日 09时31分09秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
云服务器springboot jar项目开启jmx remote监控-解决无法连接的问题
2019-03-05
Pyinstaller打包的exe文件过大的解决方法
2019-03-05
Linux的软链接跟Windows快捷方式一样?
2019-03-05
更改github的默认语言类型
2019-03-05
使用第三方sdk,微信wechat扫码登录
2019-03-05
mysql中的行转列
2019-03-05
基于LabVIEW的入门指南
2019-03-05
PCB布局系列汇总
2019-03-05
电容入门知识
2019-03-05
2019CCPC女生专场赛_K - Tetris_打表/模拟_暴力之王
2019-03-05
“/”应用程序中的服务器错误。
2019-03-05
MUI之ajax获取后台接口数据
2019-03-05
使用sqlserver 查询不连续的数据
2019-03-05
用div+css+html+js 实现图片放大
2019-03-05
(原创)在Linux上安装运行Python3(CentOS7为例)
2019-03-05
变量覆盖漏洞
2019-03-05
weblogic之cve-2015-4852
2019-03-05
Java注释
2019-03-05
水调歌头·1024
2019-03-05