考的时候,我大胆猜告终论,就是一小一大一小一大这么排
证实的话,因为咱们老是要加上相邻的最大值而减去最小值,咱们就让最大值都保持在前面ios
若是长度为奇数,要么就是大小大小大,要么是小大小大小
第一种要求是靠中间的位置填(n + 1) / 2个最大值中较大的,两边填较小的(两边只被加了一次)
第二种要求是靠中间的位置填(n + 1) / 2个最小值中较小的,两边填较大的(两边被减了一次)c++
若是长度为偶数
小大小大小大和大小大小大小显然等价ui
咱们把最小值中较大的放在最前,最大值较小的放在最后便可spa
#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; }
把每一个元组之间有两个相同元素当作惟一的连边方式,那么k个元组须要的边是
\(\frac{k(k - 1)}{2}\),咱们先看N能不能解出这个k,而后构造方法就是暴力给没连边的元组连边就行了code
#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; }
先熟练地转一下切比雪夫距离队列
容易发现这个三元组必然有两个在同一水平线或者同一竖直线上,合法的点必定是在某两个和坐标轴平行的条内,而后记录一下转完坐标系后的矩阵和,两两枚举全部水平线和竖直线上的全部点,而后计算合法的点ci
防止重复统计能够要求同一水平线上的点的三元组第三个和任两个不在同一竖直线,或者反过来get
#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; }
比赛的时候没时间想了,后来把计数方案推完,我以为这个方案真的很是假……(但我一时间没想到反例……)
竟然A了?string
这题的英文题解貌似咕着,感受能赚一点访问量了it
显然若是都是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; }