C - Align

考的时候,我大胆猜了结论,就是一小一大一小一大这么排

证明的话,由于我们总是要加上相邻的最大值而减去最小值,我们就让最大值都保持在前面

如果长度为奇数,要么就是大小大小大,要么是小大小大小

第一种要求是靠中间的位置填(n + 1) / 2个最大值中较大的,两边填较小的(两边只被加了一次)

第二种要求是靠中间的位置填(n + 1) / 2个最小值中较小的,两边填较大的(两边被减了一次)

如果长度为偶数

小大小大小大和大小大小大小显然等价

我们把最小值中较大的放在最前,最大值较小的放在最后即可

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
//#define ivorysi
#define MAXN 100005
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
int N;
int A[MAXN];
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
read(N);
for(int i = 1 ; i <= N ; ++i) read(A[i]);
sort(A + 1,A + N + 1);
if(N & 1) {
int t = N / 2 + 1;
int L = 1,R = N;int64 res = 0;
for(int i = 1 ; i <= t - 2; ++i) {
res -= 2 * A[i];
}
res = res - A[t - 1] - A[t];
for(int i = t + 1 ; i <= N ; ++i) res += 2 * A[i];
int64 tmp = 0;
t = N - (N / 2 + 1) + 1;
for(int i = N ; i >= t + 2 ; --i) tmp += 2 * A[i];
tmp += A[t + 1] + A[t];
for(int i = 1 ; i < t ; ++i) tmp -= 2 * A[i];
res = max(res,tmp);
out(res);enter;
}
else {
int L = 1,R = N;
int64 res = 0;
for(int i = 1 ; i <= N - 2 ; ++i) {
if(i & 1) res -= 2 * A[L++];
else res += 2 * A[R--];
}
res += A[R] - A[L];
out(res);enter;
}
return 0;
}

D - Crossing

把每个元组之间有两个相同元素当做唯一的连边方式,那么k个元组需要的边是

\(\frac{k(k - 1)}{2}\),我们先看N能不能解出这个k,然后构造方法就是暴力给没连边的元组连边就好了

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
//#define ivorysi
#define MAXN 100005
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
int N;
int a[1005][1005];
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
read(N);
int t = 0,k = 0;
for(int i = 1 ; i <= N ; ++i) {
t += i;
if(t >= N) {k = i;break;}
}
if(t != N) {puts("No");}
else {
puts("Yes");
out(k + 1);enter;
int cnt = 0;
for(int j = 1 ; j <= k ; ++j) {
for(int i = j ; i <= k ; ++i) {
a[j][i] = ++cnt;
}
for(int i = j + 1 ; i <= k + 1 ; ++i) {
a[i][j] = a[j][i - 1];
}
}
for(int i = 1 ; i <= k + 1 ; ++i) {
out(k);
for(int j = 1 ; j <= k ; ++j) {
space;out(a[i][j]);
}
enter;
}
}
return 0;
}

E - Equilateral

先熟练地转一下切比雪夫距离

容易发现这个三元组必然有两个在同一水平线或者同一竖直线上,合法的点一定是在某两个和坐标轴平行的条内,然后记录一下转完坐标系后的矩阵和,两两枚举所有水平线和竖直线上的所有点,然后计算合法的点

防止重复统计可以要求同一水平线上的点的三元组第三个和任两个不在同一竖直线,或者反过来

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
//#define ivorysi
#define MAXN 100005
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) out(x / 10);
putchar('0' + x % 10);
}
int H,W;
char s[305][305];
int sum[605][605];
vector<int> row[605],col[605];
int Query1(int x1,int x2,int y) {
if(x2 < x1) return 0;
if(y < 1 || y > H + W) return 0;
x2 = min(x2,H + W);
x1 = max(x1,1);
return sum[x2][y] - sum[x1 - 1][y] - sum[x2][y - 1] + sum[x1 - 1][y - 1];
}
int Query2(int x,int y1,int y2) {
if(y2 < y1) return 0;
if(x < 1 || x > H + W) return 0;
y2 = min(y2,H + W);
y1 = max(y1,1);
return sum[x][y2] - sum[x][y1 - 1] - sum[x - 1][y2] + sum[x - 1][y1 - 1];
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
read(H);read(W);
for(int i = 1 ; i <= H ; ++i) {
scanf("%s",s[i] + 1);
}
for(int i = 1 ; i <= H ; ++i) {
for(int j = 1 ; j <= W ; ++j) {
if(s[i][j] == '#') {
sum[i + j][i - j + W]++;
row[i + j].pb(i - j + W);
col[i - j + W].pb(i + j);
}
}
}
for(int i = 1 ; i <= H + W ; ++i) {
for(int j = 1 ; j <= H + W ; ++j) {
sum[i][j] += sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];
}
}
int64 ans = 0;
for(int i = 1 ; i <= H + W ; ++i) {
int s = row[i].size();
sort(row[i].begin(),row[i].end());
for(int j = 0 ; j < s ; ++j) {
for(int k = j + 1 ; k < s ; ++k) {
int l = row[i][k] - row[i][j];
ans += Query2(i - l,row[i][j],row[i][k]);
ans += Query2(i + l,row[i][j],row[i][k]);
}
}
}
for(int i = 1 ; i <= H + W ; ++i) {
int s = col[i].size();
sort(col[i].begin(),col[i].end());
for(int j = 0 ; j < s ; ++j) {
for(int k = j + 1 ; k < s ; ++k) {
int l = col[i][k] - col[i][j];
ans += Query1(col[i][j] + 1,col[i][k] - 1,i - l);
ans += Query1(col[i][j] + 1,col[i][k] - 1,i + l);
}
}
}
out(ans);enter;
return 0;
}

F - Circular

比赛的时候没时间想了,后来把计数方案推完,我觉得这个方案真的非常假……(但我一时间没想到反例……)

居然A了?

这题的英文题解貌似咕着,感觉能赚一点访问量了

显然如果都是1的话方案是\(n!\),这个特判掉

其次这个序列必然是相同的数都在连续的一段,不能有穿插的数,例如样例3 1 4 1 5,很好想,不说了

然后我们找到1所在的段长,这肯定是序列进行的操作次数

为了方便,我们断环为链,把1扯出来作为第一个数

然后剩下的段长都不能超过这个长度,否则输出0

设段长为\(len\),当前位置的数\(i\)肯定是比\([i,i + len - 1]\)的最大值要大,这个你单调队列还是写rmq随意吧,都求出来,记为\(val[i]\)

然后对于连续一段的数\([l,r]\)这个数位\(num\),这个限制了\(num\)在某个区间里

这个区间就是\([r + 1 - len,l]\)我们计算一下这个区间里的数有几个\(val[i]\)和\(num\)相同,这个时候,假如这个值是0,那么无解

统计的时候我们记录一个\(cnt[x]\)表示\(val[i] == x\)的个数,处理成前缀和

统计的时候枚举每一个数,假如这个数有必选位置,我们乘上必选位置的个数,否则乘上\(cnt[i] - (i - 1)\)也就是\(cnt[i]\)是\(i\)能在的位置,这些位置有且仅有\(i - 1\)个被占用了

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define space putchar(' ')
#define enter putchar('\n')
#define mp make_pair
#define pb push_back
//#define ivorysi
#define MAXN 300005
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
const int MOD = 998244353;
int N,a[MAXN * 2],A[MAXN],st[MAXN][20],val[MAXN],len[MAXN],must[MAXN],sum[MAXN],ql,qr,cnt[MAXN];
bool vis[MAXN];
int inc(int a,int b) {
return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
return 1LL * a * b % MOD;
}
int Query(int l,int r) {
int t = len[r - l + 1];
return max(st[l][t],st[r - (1 << t) + 1][t]);
}
void Move(int l,int r) {
while(qr < r) sum[val[++qr]]++;
while(ql < l) sum[val[ql++]]--;
}
void Solve() {
read(N);bool all_1 = 1;
for(int i = 1 ; i <= N ; ++i) {read(a[i]);a[i + N] = a[i];if(a[i] != 1) all_1 = 0;}
if(all_1) {
int res = 1;
for(int i = 1 ; i <= N ; ++i) res = mul(res,i);
out(res);enter;return;
}
int s = 0;
for(int i = 2 ; i <= 2 * N ; ++i) {
if(a[i] == 1 && a[i - 1] != 1) {
s = i;
break;
}
}
if(!s) {puts("0");return;}
for(int i = 1 ; i <= N ; ++i) A[i] = a[s++];
int p = 1;
while(A[p] == 1) ++p;
--p;
int l = 0;
for(int i = 1 ; i <= N ; ++i) {
if(A[i] != A[i - 1]) {
if(vis[A[i]]) {puts("0");return;}
vis[A[i]] = 1;l = 0;
}
++l;
if(l > p) {puts("0");return;}
}
for(int i = 1 ; i <= N ; ++i) st[i][0] = A[i];
for(int j = 1 ; j <= 19 ; ++j) {
for(int i = 1 ; i <= N ; ++i) {
if(i + (1 << j) - 1 > N) break;
st[i][j] = max(st[i][j - 1],st[i + (1 << j - 1)][j - 1]);
}
}
for(int i = 2 ; i <= N ; ++i) len[i] = len[i / 2] + 1;
for(int i = 1 ; i <= N ; ++i) {
int r = min(i + p - 1,N);
val[i] = Query(i,r);
}
int t = 0;ql = 1,qr = 0;
for(int i = 1 ; i <= N ; ++i) {
if(A[i] != A[i - 1]) {
if(t) {
s = max(1,i - p);
Move(s,t);
must[A[i - 1]] = sum[A[i - 1]];
if(!sum[A[i - 1]]) {puts("0");return;}
}
t = i;
}
}
s = max(1,N - p + 1);
Move(s,t);
must[A[N]] = sum[A[N]];
if(!sum[A[N]]) {puts("0");return;}
for(int i = 1 ; i <= N ; ++i) cnt[val[i]]++;
for(int i = 1 ; i <= N ; ++i) cnt[i] += cnt[i - 1];
int ans = 1;
for(int i = 1 ; i <= N ; ++i) {
if(must[i]) {ans = mul(ans,must[i]);}
else ans = mul(ans,cnt[i] - (i - 1));
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
return 0;
}

【AtCoder】Tenka1 Programmer Contest(C - F)的更多相关文章

  1. 【AtCoder】Tenka1 Programmer Contest 2019

    Tenka1 Programmer Contest 2019 C - Stones 题面大意:有一个01序列,改变一个位置上的值花费1,问变成没有0在1右边的序列花费最少多少 直接枚举前i个都变成0即 ...

  2. 【AtCoder】Tenka1 Programmer Contest

    C - 4/N 列出个方程枚举解一下 #include <bits/stdc++.h> #define fi first #define se second #define pii pai ...

  3. 【AtCoder】AISing Programming Contest 2019

    本来以为是1199rated的..仔细一看发现是1999,所以就做了一下 这场涨分很轻松啊...为啥又没打 等pkuwc考完我一定打一场atcoder(咕咕咕,咕咕咕,咕咕咕咕咕咕咕~) 但是其实我思 ...

  4. 【AtCoder】M-SOLUTIONS Programming Contest

    M-SOLUTIONS Programming Contest A - Sum of Interior Angles #include <bits/stdc++.h> #define fi ...

  5. 【AtCoder】Yahoo Programming Contest 2019

    A - Anti-Adjacency K <= (N + 1) / 2 #include <bits/stdc++.h> #define fi first #define se se ...

  6. 【AtCoder】KEYENCE Programming Contest 2019

    A - Beginning 这个年份恐怕需要+2 #include <bits/stdc++.h> #define fi first #define se second #define p ...

  7. 【AtCoder】Dwango Programming Contest V题解

    A - Thumbnail 题意简述:给出N个数,找出N个数中和这N个数平均值绝对值最小的数 根据题意写代码即可= = #include <bits/stdc++.h> #define f ...

  8. Tenka1 Programmer Contest D - Crossing

    链接 Tenka1 Programmer Contest D - Crossing 给定\(n\),要求构造\(k\)个集合\({S_k}\),使得\(1\)到\(n\)中每个元素均在集合中出现两次, ...

  9. Tenka1 Programmer Contest C - Align

    链接 Tenka1 Programmer Contest C - Align 给定一个序列,要求重新排列最大化\(\sum_{i=2}^{i=n} |a_i-a_{i-1}|\),\(n\leq 10 ...

随机推荐

  1. bzoj1038

    这是一道非常有意思的题目 Description 致力于建设全国示范和谐小村庄的H村村长dadzhi,决定在村中建立一个瞭望塔,以此加强村中的治安.我们将H村抽象为一维的轮廓.如下图所示 我们可以用一 ...

  2. Fib的奇怪定理 : gcd(F[n],F[m])=F[gcd(n,m)]

    引理1:gcd(F[n],f[n-1])=1 因为 F[n]=f[n-1]+F[n-2] 所以 gcd(F[n],f[n-1]) = gcd(F[n-1]+F[n-2],F[n-1]) gcd的更损相 ...

  3. 【转】spi测试自发自收(中断通信方式)

    1.初始化spi时钟 void spiRccinit(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); RCC_APB2Peri ...

  4. 大数据高性能数据库Redis在Windows上的使用教程

    Redis学习笔记----Redis在windows上的安装配置和使用 Redis简介 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括s ...

  5. 在Linux中以普通用户开机自动运行脚本程序

    测试环境:CentOS6.5 管理员:root 普通用户:test1 实现目标:在Linux启动时,以普通用户test1自动运行位于根目录下的脚本程序test.py,该程序会在每次执行时自动向本地日志 ...

  6. mycat 入门教程

    mycat 入门教程 之前已经对mycat的配置进行了详细记得介绍,下面就是一个mycat分库的小例子 schema.xml配置 <?xml version="1.0"?&g ...

  7. 修改el-table滚动条样式

    <include file="Trade:header" /> <style type="text/css" media="scre ...

  8. Dubbo学习笔记4:服务消费端泛化调用与异步调用

    本文借用dubbo.learn的Dubbo API方式来解释原理. 服务消费端泛化调用 前面我们讲解到,基于Spring和基于Dubbo API方式搭建简单的分布式系统时,服务消费端引入了一个SDK二 ...

  9. hdu 5385 The path

    http://acm.hdu.edu.cn/showproblem.php?pid=5385 题意: 给定一张n个点m条有向边的图,构造每条边的边权(边权为正整数),令d(x)表示1到x的最短路,使得 ...

  10. CF876 F 思维 枚举

    给你n个数,问有几个区间满足,区间内或操作大于区间内的任意数. 首先可以知道,两数或操作的结果必定不会小于两者间的最大值,也就是说对于一个区间中,不合法的状态只有两值或相等.那么我们可以考虑枚举每个数 ...