T1
考虑从后往前去做,随机化字母权值,考虑两个字符,一个设为正的权值,一个设为负的权值,两两就可以抵消,若有一个后缀权值等于另一个后缀权值且长度为偶数,就肯定有一个回文串,若有一个后缀权值等于另一个后缀权值加减一个字母的权值且长度为奇数,就也肯定有一个回文串,存下来,离散化即可。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 10, M = 28;
int n, m, ans;
char c[N];
int val[M], sum[N], p[N], mp[N][2];
mt19937 rd(40491522);
void solve(){
for (int i = 0; i < 26; i++) val[i] = rd();
for (int i = n; i >= 1; i--){
p[i] = sum[i] = sum[i + 1] + val[c[i] - 'a'];
val[c[i] - 'a'] = -val[c[i] - 'a'];
}
sort(p + 1, p + n + 1);
m = unique(p + 1, p + n + 1) - p - 1;
for (int i = n; i >= 1; i--){
int k = lower_bound(p + 1, p + m + 1, sum[i]) - p;
if (mp[k][i & 1]) ans = max(ans, mp[k][i & 1] - i);
if (((n - i + 1) & 1) == 0 && !sum[i]) ans = max(ans, n - i + 1);
for (int d = 0; d < 26; d++){
int y = sum[i] - val[d];
k = lower_bound(p + 1, p + m + 1, y) - p;
if (p[k] == y && mp[k][(i & 1) ^ 1]) ans = max(ans, mp[k][(i & 1) ^ 1] - i);
if ((n - i + 1) & 1 && !y) ans = max(ans, n - i + 1);
y = sum[i] + val[d];
k = lower_bound(p + 1, p + m + 1, y) - p;
if (p[k] == y && mp[k][(i & 1) ^ 1]) ans = max(ans, mp[k][(i & 1) ^ 1] - i);
if ((n - i + 1) & 1 && !y) ans = max(ans, n - i + 1);
}
k = lower_bound(p + 1, p + m + 1, sum[i]) - p;
if (!mp[k][i & 1]) mp[k][i & 1] = i;
}
cout << ans;
}
signed main(){
freopen("easygame.in", "r", stdin);
freopen("easygame.out", "w", stdout);
ios::sync_with_stdio;
cin.tie(0);cout.tie(0);
cin >> (c + 1);
n = strlen(c + 1);
solve();
return 0;
}
T2
从 \(1\) 号节点开始间隔染色,圆点都在叶子上,对于每个方点最少连一个环的边双,最多能连一个竞赛图,于是直接暴力连边即可。
#include<iostream>
#define int long long
using namespace std;
inline int read(){register int x = 0, f = 1;register char c = getchar();while (c < '0' || c > '9'){if (c == '-') f = -1;c = getchar();}while (c >= '0' && c <= '9'){x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}return x * f;}
inline void write(int x){if (x < 0) putchar('-'), x = -x;if (x > 9) write(x / 10);putchar(x % 10 + '0');}
const int N = 1e6 + 10;
int n, m, k;//m点,k边
struct edge{
int v, nxt;
}e[N << 1];
int head[N], cnt;
void add(int u, int v){
e[++cnt] = (edge){v, head[u]};
head[u] = cnt;
}
int p[N], top, q[N], toq, dep[N], sw[N];//p white q black
bool vis[N], son[N];
void col(int u, int fa, bool c){
if (c) q[++toq] = u;
else p[++top] = u;
dep[u] = dep[fa] + 1;
int tot = 0;
for (int i = head[u]; i; i = e[i].nxt){
int v = e[i].v;
if (v == fa) continue;
col(v, u, c ^ 1);
tot++;
}
if (!tot) son[u] = 1;
}
int stk[N], t, ID[N];
signed main(){
freopen("blocktree.in", "r", stdin);
freopen("blocktree.out", "w", stdout);
n = read(), m = read(), k = read();
for (int i = 1; i < n; i++){
int u = read(), v = read();
add(u, v), add(v, u);
}
col(1, 0, 0);
int maxn = 0;
for (int i = 1; i <= n; i++) maxn = max(maxn, dep[i]);
for (int i = 1; i <= n; i++){
if (son[i] && (maxn & 1) != (dep[i] & 1)){
cout << "No";
return 0;
}
}
if (!(maxn & 1)){
for (int i = 1; i <= top; i++) sw[i] = p[i];
for (int i = 1; i <= toq; i++) p[i] = q[i];
for (int i = 1; i <= top; i++) q[i] = sw[i];
swap(top, toq);
}
if (top != m){
cout << "No";
return 0;
}
int res1 = 0, res2 = 0;
for (int u = 1; u <= toq; u++){
int tot = 0;
for (int i = head[q[u]]; i; i = e[i].nxt) tot++;
if (tot != 2) res1 += tot, res2 += tot * (tot - 1) / 2;
else res1++, res2++;
vis[q[u]] = 1;
}
if (k < res1 || k > res2){
cout << "No";
return 0;
}
cout << "Yes\n";
int id = 0;
for (int i = 1; i <= n; i++){
if (vis[i]) cout << 0 << ' ';
else cout << (ID[i] = ++id) << ' ';
}
cout << '\n';
bool f = 0;
for (int u = 1; u <= toq; u++){
for (int i = head[q[u]]; i; i = e[i].nxt) stk[++t] = e[i].v;
for (int i = 1; i < t; i++) cout << ID[stk[i]] << ' ' << ID[stk[i + 1]] << '\n';
if (t != 2){
cout << ID[stk[t]] << ' ' << ID[stk[1]] << '\n';
}
for (int i = 1; i <= t; i++){
if (f) break;
for (int j = i; j <= t; j++){
if (i == j || j == i + 1 || (j == t && i == 1)) continue;
if (k > res1) cout << ID[stk[i]] << ' ' << ID[stk[j]] << '\n', k--;
else{
f = 1;
break;
}
}
}
t = 0;
}
return 0;
}
T3
显然有一个二维数点的做法,接下来就只需要考虑如何求出这样的点,设 \(x = p_1^{\alpha_1}p_2^{\alpha_2}\dots p_n^{\alpha_n}\),\(y = p_1^{\beta_1}p_2^{\beta_2}\dots p_n^{\beta_n}\),等价于 \(\gcd(\max(\alpha_1, \beta_1),\dots ,\max(\alpha_n, \beta_n))\not= 1\),于是写一个搜索就行了。
#include<iostream>
#include<algorithm>
using namespace std;
inline int read(){register int x = 0, f = 1;register char c = getchar();while (c < '0' || c > '9'){if (c == '-') f = -1;c = getchar();}while (c >= '0' && c <= '9'){x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}return x * f;}
inline void write(int x){if (x < 0) putchar('-'), x = -x;if (x > 9) write(x / 10);putchar(x % 10 + '0');}
const int N = 1e6 + 10, M = 1e6;
int T, ans[N];
int p[N], cnt;
bool prime[N];
int gcd(int a, int b){
return (b == 0 ? a : gcd(b, a % b));
}
void pri(){
for (int i = 2; i <= 1e3; i++){
if (!prime[i]) p[++cnt] = i;
for (int j = 1; j <= cnt && i * p[j] <= 1e3; j++){
prime[i * p[j]] = 1;
if (i % p[j] == 0) break;
}
}
}
struct node{
int x, y, type, id;
bool operator < (const node &b) const{
return (x != b.x ? x < b.x : type < b.type);
}
}q[N * 8];
int opt;
int GCD[25][25];
void dfs(int x, int y, int g, int lst){
if (lst == cnt + 1 || x * p[lst] > M && y * p[lst] > M){
q[++opt] = (node){x, y, 0, 0};
return;
}
long long res1 = 1;
for (int i = 0; x * res1 <= M; i++, res1 *= p[lst]){
long long res2 = 1;
for (int j = 0; y * res2 <= M; j++, res2 *= p[lst]){
int G = GCD[g][max(i, j)];
if (G == 1) continue;
dfs(x * res1, y * res2, G, lst + 1);
}
}
}
void init(){
pri();
for (int i = 0; i <= 23; i++)
for (int j = 0; j <= 23; j++) GCD[i][j] = gcd(i, j);
dfs(1, 1, 0, 1);
}
int t[N];
int lowbit(int x){return x & (-x);}
void add(int x, int k){
for (int i = x; i <= M; i += lowbit(i)) t[i] += k;
}
int query(int x){
int res = 0;
for (int i = x; i; i -= lowbit(i)) res += t[i];
return res;
}
int main(){
freopen("unnamed.in", "r", stdin);
freopen("unnamed.out", "w", stdout);
init();
T = read();
for (int i = 1; i <= T; i++){
int a = read(), b = read(), c = read(), d = read();
q[++opt] = (node){b, d, 1, i};
q[++opt] = (node){a - 1, d, 2, i};
q[++opt] = (node){b, c - 1, 2, i};
q[++opt] = (node){a - 1, c - 1, 1, i};
}
sort(q + 1, q + opt + 1);
for (int i = 1; i <= opt; i++){
if (q[i].type == 0) add(q[i].y, 1);
if (q[i].type == 1) ans[q[i].id] += query(q[i].y);
if (q[i].type == 2) ans[q[i].id] -= query(q[i].y);
}
for (int i = 1; i <= T; i++) cout << ans[i] << '\n';
return 0;
}
T4
不会。
标签:20241023noip,int,sum,权值,共同体,mp,&&,ans,OIFC From: https://www.cnblogs.com/bryceyyds/p/18521209