Manthan, Codefest 19(Div. 1 + Div. 2)
A. XORinacci
签到。
Code
/*
* Author: heyuhhh
* Created Time: 2020/2/26 9:26:33
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
int f[3];
int a, b, n;
void run(){
cin >> a >> b >> n;
f[0] = a, f[1] = b;
f[2] = a ^ b;
n %= 3;
cout << f[n] << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
int T; cin >> T;
while(T--) run();
return 0;
}
B. Uniqueness
题意:
给出\(n,n\leq 2000\)个数,现在可以至多删除一段区间\([l,r]\)。最后要使得剩下的数互不相同。问最终删除区间的最小长度为多少。
思路:
枚举左、右端点,用一个\(set\)来维护剩下的元素即可。
时间复杂度\(O(n^2logn)\)。
Code
/*
* Author: heyuhhh
* Created Time: 2020/2/26 9:34:06
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2000 + 5;
int n;
int a[N];
void run(){
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
set <int> s;
int ans = n;
for(int l = 0; l <= n; l++) {
if(s.count(a[l])) break;
s.insert(a[l]);
ans = min(ans, n - l);
set <int> t;
for(int r = n; r > l; r--) {
if(s.count(a[r]) || t.count(a[r])) break;
t.insert(a[r]);
ans = min(ans, r - l - 1);
}
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}
C. Magic Grid
题意:
现在要构造一个\(n\cdot n\)的矩阵,矩阵里面的数互不相同,取值为\([0,n^2-1]\),并且使得矩阵中行、列异或值都相同。
思路:
归纳一下,直接将整个矩阵按\(k\)分块,分成多个\(4\cdot 4\)的小矩阵构造就行。
正确性因为所有的数都加上\(2^x\)过后,最后的异或值不会发生变化。
代码如下:
Code
/*
* Author: heyuhhh
* Created Time: 2020/2/26 11:02:11
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1000 + 5;
int n;
int a[N][N];
void run() {
int k = n / 4;
int now = 0;
for(int i = 1; i <= k; i++) {
for(int j = 1; j <= k; j++) {
for(int x = (i - 1) * 4 + 1; x <= i * 4; x++) {
for(int y = (j - 1) * 4 + 1; y <= j * 4; y++) {
a[x][y] = now++;
}
}
}
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
cout << a[i][j] << " \n"[j == n];
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
while(cin >> n) run();
return 0;
}
D. Restore Permutation
直接从后往前构造即可,利用树状数组+二分查询来确定一个位置的值,时间复杂度\(O(nlog^2n)\)。
代码如下:
Code
/*
* Author: heyuhhh
* Created Time: 2020/2/26 16:34:24
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2e5 + 5;
int n;
int a[N];
ll s[N];
struct BIT {
ll c[N];
int lowbit(int x) {return x & (-x);}
void add(int x, int v) {
for(; x < N; x += lowbit(x)) c[x] += v;
}
ll query(int x) {
ll res = 0;
for(; x; x -= lowbit(x)) res += c[x];
return res;
}
}bit;
void run(){
cin >> n;
for(int i = 1; i <= n; i++) cin >> s[i];
for(int i = 1; i <= n; i++) bit.add(i, i);
for(int i = n; i >= 1; i--) {
int l = 1, r = n + 1, mid;
while(l < r) {
mid = (l + r) >> 1;
if(bit.query(mid) > s[i]) r = mid;
else l = mid + 1;
}
a[i] = l;
bit.add(a[i], -a[i]);
}
for(int i = 1; i <= n; i++) cout << a[i] << " \n"[i == n];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}
E. Let Them Slide
题意:
有一个\(n\cdot w,n,w\leq 10^6\)的表,现在有\(n\)个数组,每个数组中元素的取值范围为\([-10^9,10^9]\),所有数组的长度之和不超过\(10^6\)。
每一个数组可以在表内左右移动。
问最后对于每一列,其和的最大值为多少。
思路:
- 对每一个数组单独考虑其贡献:容易发现一个数组对列的贡献为\(1,2,\cdots,max,\cdots,max,max-1,\cdots,2,1\)的形式。
- 形象点来说,一个数组的贡献一开始为一个从\(1\)开始,有着最大宽度的滑动窗口;最后窗口宽度会回到\(1\)。中间有一段对列的贡献始终相同。
- 那么我们中间的那一段可以直接利用差分来处理,而前面部分和后面部分我们直接暴力计算贡献就行。用\(set\)的话好写一点,时间复杂度为\(O(len\cdot log_{len})\)。
- 注意一点细节:因为可能窗口中的最大值为负数,在某些位置,我们可以让这一列为空,那么最后的取值就是\(0\)了。对于这一点的处理可以找一下关系:设当前数组的长度为\(k\),那么\(r=w-k\),\([1,r],[w-k+1,w]\)这段可以取\(0\);我们最后窗口的上界为\(min(k,w-k+1)\)。
- 显然当\(2k\leq w\)时,所有位置均可取\(0\);
- 当\(2k>w\)即上界\(max=k\)时,此时\(r<k\),那么\([1,r]、[w-k+1,w]\)这两段区间我们暴力计算的时候可以直接计算。
最终总的时间复杂度为\(O(nlogn)\),这里的\(n\)为数组总长度。
细节见代码:
Code
/*
* Author: heyuhhh
* Created Time: 2020/2/26 17:04:19
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.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 INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e6 + 5;
int n, w;
int a[N];
ll ans[N], sum[N];
void run(){
cin >> n >> w;
multiset <int> S;
for(int i = 1; i <= n; i++) {
int k; cin >> k;
for(int j = 1; j <= k; j++) cin >> a[j];
S.clear();
int Max = min(k, w - k + 1), r = w - k;
if(2 * k <= w) {
for(int j = 1; j <= k; j++) if(a[j] < 0) a[j] = 0;
}
for(int j = 1; j <= w; j++) {
if(j <= Max) {
S.insert(a[j]);
} else if(j <= min(k, w - Max + 1)) {
S.insert(a[j]);
auto it = S.lower_bound(a[j - Max]);
assert(it != S.end());
S.erase(it);
} else if(j > w - Max + 1) {
auto it = S.lower_bound(a[k - Max + j - (w - Max + 1)]);
assert(it != S.end());
S.erase(it);
} else {
int st = j;
int ed = w - Max + 1 + 1;
auto it = S.end(); it--;
int now = *it;
sum[st] += now, sum[ed] -= now;
j = w - Max + 1;
continue;
}
auto it = S.end(); it--;
int now = *it;
if(j <= r || j >= w - r + 1) now = max(0, now);
ans[j] += now;
}
assert(S.size() == 1);
}
for(int i = 1; i <= w; i++) {
sum[i] += sum[i - 1];
ans[i] += sum[i];
}
for(int i = 1; i <= w; i++) {
cout << ans[i] << " \n"[i == w];
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}
F. Bits And Pieces
题意:
给出序列\(a_{1,2\cdots,n},n\leq 10^6\)。
现在要找最大的\(a_i|(a_j\& a_k)\),其中\((i,j,k)\)满足\(i<j<k\)。
思路:
- 显然我们可以枚举\(a_i\),那么问题就转换为如何快速找\(a_j\& a_k\)。
- 暴力的方法就是从高到低枚举二进制每一位,然后用各种方法乱搞。
- 因为最后要使得结果最大,我们二进制从高到底枚举时肯定是贪心来考虑的:即如果有两个数他们的与在这一位为\(1\),那么最后的答案中一定有这一位。
- 那么我们逐位考虑,并且考虑是否有两个在右边的数他们与的结果为当前答案的超集即可,有的话答案直接加上这一位。
- 那么可以用\(sos\ dp\)处理超集的信息,并且维护在最右端的两个位置,之后贪心来处理即可。
稍微来说一下这个\(sos\ dp\),我们定义\(dp[i][mask]\)为状态为\(mask\)时,处理了二进制后面\(i\)位的超集信息后,当前最右端的两个位置。那么转移时枚举第\(i+1\)位,若这一位为\(1\),那么\(dp[i][mask]\rightarrow dp[i+1][mask-(1<<(i+1))],dp[i+1][mask]\)进行转移即可。
代码中滚动掉了一维。
细节见代码:
Code
/*
* Author: heyuhhh
* Created Time: 2020/2/27 10:51:39
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2e6 + 5;
int n;
int a[N];
pii dp[N];
void add(int x, int id) {
if(dp[x].fi == -1) {
dp[x].fi = id;
} else if(dp[x].se == -1) {
if(dp[x].fi == id) return;
dp[x].se = id;
if(dp[x].fi < dp[x].se) swap(dp[x].fi, dp[x].se);
} else if(dp[x].fi < id) {
dp[x].se = dp[x].fi;
dp[x].fi = id;
} else if(dp[x].se < id) {
if(dp[x].fi == id) return;
dp[x].se = id;
}
}
void merge(int x1, int x2) {
add(x1, dp[x2].fi);
add(x1, dp[x2].se);
}
void run() {
memset(dp, -1, sizeof(dp));
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> a[i];
add(a[i], i);
}
for(int i = 0; i < 21; i++) {
for(int j = 0; j < N; j++) if(j >> i & 1) {
merge(j ^ (1 << i), j);
}
}
int ans = 0;
for(int i = 1; i <= n - 2; i++) {
int lim = (1 << 21) - 1;
int cur = a[i] ^ lim, res = 0;
for(int j = 20; j >= 0; j--) if(cur >> j & 1) {
if(dp[res ^ (1 << j)].se > i) {
res ^= (1 << j);
}
}
ans = max(ans, res | a[i]);
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
run();
return 0;
}
Manthan, Codefest 19(Div. 1 + Div. 2)的更多相关文章
- Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-D. Restore Permutation-构造+树状数组
Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-D. Restore Permutation-构造+树状数组 [Pro ...
- Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-C. Magic Grid-构造
Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-C. Magic Grid-构造 [Problem Descripti ...
- Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-E. Let Them Slide-思维+数据结构
Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-E. Let Them Slide-思维+数据结构 [Problem ...
- 云端搭建Linux学习环境 链接https://edu.aliyun.com/article/19 (阿里云ECS服务器 )课堂
云端搭建Linux学习环境 链接https://edu.aliyun.com/article/19 1. 开通云服务器 2 1.包年包月 按量付费(适合测试数据的时候) 2 2.地域 服务器数 ...
- Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)D(树状数组)
//树状数组中数组的特性,有更巧妙的方法.//我们知道在树状数组中,对于数组tree[i],它所维护的区间为[i−lowbit(i)+1,i]//所以对于tree[2^i],它所维护的区间就为[1,2 ...
- RMQ+差分处理(Let Them Slide)Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)
题意:https://codeforc.es/contest/1208/problem/E 现有n行w列的墙,每行有一排连续方块,一排方块可以左右连续滑动,且每个方块都有一个价值,第i 列的价值定义为 ...
- 线段树维护最后一个0的位置(Restore Permutation)Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)
题意:https://codeforc.es/contest/1208/problem/D 给你长度为n的序列,s[i]的值为p[1]到p[i-1]中比p[i]小的数的和,让你求出p序列. 思路: 首 ...
- Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)E(多重集维护)
#define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h>using namespace std;long long ans[1000007]; ...
- Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)B(SET)
#define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h>using namespace std;int a[2007];set<int& ...
随机推荐
- 操作COOKIE的函数
一个同学慧涛分享给我的他写的操作cookie的函数,贴出来,做个笔记: //操作cookie //删除cookie hcookie('cookiename','','del'); //查询cookie ...
- 在Visual Studio 2017中,.NET(C#)通过Oracle.ManagedDataAccess来连接Oracle数据库
C#如何通过Oracle.ManagedDataAccess来连接Oracle数据库 1.先创建一个项目,鼠标右击项目中的引用,再点击管理NuGet程序包(也可以先下载dll文件,再选添加引用),在搜 ...
- windows下的环境搭建配置redis
http://blog.csdn.net/spring21st/article/details/11176723
- Laravel 6.X + Vue.js 2.X + Element UI 开发知乎流程
本流程参照:CODECASTS的Laravel Vuejs 实战:开发知乎 视频教程 1项目环境配置和用户表设计 2Laravel 开发知乎:用户注册 3Laravel 开发知乎:用户登录 4Lara ...
- 如何去掉Eclipse注释中英文单词的拼写错误检查
- PTA的Python练习题(三)
继续在PTA上编写Python的编程题. 从 第2章-11 求平方与倒数序列的部分和 开始 1. a,b=map(int,input().split()) s=0 while(a<=b): s= ...
- 【剑指Offer面试编程题】题目1356:孩子们的游戏(圆圈中最后剩下的数)--九度OJ
题目描述: 每年六一儿童节,JOBDU都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此.HF作为JOBDU的资深元老,自然也准备了一些小游戏.其中,有个游戏是这样的:首先,让小朋友们围成一个大圈. ...
- hdfs dfs ls /列出了本地根目录下文件夹和文件Warning: fs.defaultFS is not set when running "ls" command
[root@node01 customShells]# hdfs dfs -ls /Warning: fs.defaultFS is not set when running "ls&quo ...
- Spark入门:第4节 Spark程序:1 - 9
五. Spark角色介绍 Spark是基于内存计算的大数据并行计算框架.因为其基于内存计算,比Hadoop中MapReduce计算框架具有更高的实时性,同时保证了高效容错性和可伸缩性.从2009年诞生 ...
- Linux三剑客之awk精讲(基础与进阶)
第1章 awk基础入门 要弄懂awk程序,必须熟悉了解这个工具的规则.本实战笔记的目的是通过实际案例或面试题带同学们熟练掌握awk在企业中的用法,而不是awk程序的帮助手册. 1.1 awk简介 一种 ...