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& ...
随机推荐
- vue 中 限制 input 输入数字、小数位数等
限制小数位数 <input type="number" @keydown="handleInput2" placeholder="请输入或查看& ...
- JavaSE复习~运算符与表达式
运算符 运算符:进行特定操作的符号 表达式:用运算符进行操作的式子 算术运算符 首先是加减乘除:+.-.*./还有取余:% 整数进行算术操作得到的还是整数,例如整数使用 / 得到的是整数(商的整数部分 ...
- window下jenkins+allure+邮箱发送
一.安装allure 1)下载 allure.zip 下载地址:allure-github: https://github.com/allure-framework/allure2 2)解压到本地目录 ...
- ASA-有关AAA用户登录的问题
问题示例:I have created a test user that is set to privilege 15 in the config: When I log in to the ASA ...
- win10上的程序兼容win7、xp等
- STM的低功耗系列
STM32L0的2个新增外设:一是集成了晶振的USB,第二高精度的12位或16位ADC: 特色外设LUART:传统的MCU当CPU睡眠,进入低功耗模式下,外设是关闭的,因为时钟是关闭的,而意法半导体的 ...
- I/O-<File实例>
File n=new File("D:\2016.txt"); System.out.println("文件是否存在"+n.exists()); System. ...
- SQL SERVER用户表信息
可以使用下面这个语句查看用户表的相关信息 RowCount 记录数 FileGroup 文件组 PartitionScheme 分区结构 IsPartitioned 是否分区 SELECT tbl.n ...
- TreeView 中 MVVM Command Binding
<HierarchicalDataTemplate x:Key="TreeNodes" ItemsSource="{Binding Path=Childs,Mode ...
- GIT使用教程——命令详解
$ git init 当前目录建立GIT可以管理的仓库(版本库),生成一个.git的隐藏文件夹 $ git add <filename> 将工作区的文件修改添加到版本库的暂存区 $ git ...