CSP-S模拟11
A. 回文
经典 \(dp\) ,两边同时走,三维状态表示走了几步,左上出发走到哪行,右下出发走到哪行
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 505;
const int mod = 993244853;
int f[2][maxn][maxn], n, m, nt, zt;
char mp[maxn][maxn];
void add(int &x, int y){
x += y; x = x >= mod ? x - mod : x;
}
bool check(int x, int y){return x > 0 && y > 0 && x <= n && y <= m;}
bool can(int x, int y, int xx, int yy){
// printf("chk : %d %d %d %d\n", x, y, xx ,yy);
return check(x, y) && check(xx, yy) && mp[x][y] == mp[xx][yy];
}
void upd(int x, int y, int xx, int yy){
if(xx < x || yy < y)return;
if(can(x, y + 1, xx, yy - 1))add(f[nt][x][xx], f[zt][x][xx]);
if(can(x, y + 1, xx - 1, yy))add(f[nt][x][xx - 1], f[zt][x][xx]);
if(can(x + 1, y, xx, yy - 1))add(f[nt][x + 1][xx], f[zt][x][xx]);
if(can(x + 1, y, xx - 1, yy))add(f[nt][x + 1][xx - 1], f[zt][x][xx]);
}
int main(){
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; ++i)scanf("%s",mp[i] + 1);
f[0][1][n] = mp[1][1] == mp[n][m];
int c = (n + m - 1) / 2;
if((n + m) % 2 == 0)++c;
for(int i = 1; i < c; ++i){
nt = i & 1, zt = 1 - nt;
int sum = i + 1;
int up = min(n, sum - 1);
for(int d1 = 1; d1 <= up; ++d1)
for(int d2 = 1; d2 <= up; ++d2){
int x = d1, y = sum - d1;
int xx = n - d2 + 1, yy = m + n - i - xx + 1;
if(x <= xx && y <= yy && f[zt][x][xx])upd(x, y, xx, yy);
f[zt][x][xx] = 0;
}
}
int ans = 0;
nt = c & 1;
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
int x = i, y = c - i + 1;
int xx = n - j + 1, yy = m + n - c - xx + 1;
// printf("%d %d %d %d\n",x, y, xx, yy);
if(x <= xx && y <= yy && check(x, y) && check(xx, yy))add(ans, f[1 - nt][x][xx]);
}
}
printf("%d\n",ans);
return 0;
}
B. 快速排序
你如果像我一样一直考虑如何优化他的代码,别想了,没救
发现就是把数移到前面比他大的数前面,整体还是有序的
那么每次二分一下就行了
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 500005;
const int inf = 2147483647;
int n;
char c[15];
int a[maxn], b[maxn];
bool vis[maxn];
void solve(){
scanf("%d",&n);
for(int i = 1; i <= n; ++i){
a[i] = 0;
scanf("%s", c + 1);
if(c[1] == 'n')a[i] = inf;
else{
int s = strlen(c + 1);
for(int j = 1; j <= s; ++j){
a[i] = (a[i] << 3) + (a[i] << 1) + (c[j] ^ 48);
}
}
}
int p = 0;
for(int i = 1; i <= n; ++i)if(a[i] != inf)b[++p] = a[i];
sort(b + 1, b + p + 1);
int mx = 0;
int l = 1;
for(int i = 1; i <= n; ++i){
if(a[i] == inf)printf("nan ");
else{
if(mx <= a[i]){
int now = lower_bound(b + l, b + p + 1, a[i]) - b;
for(int j = l; j <= now; ++j)printf("%d ",b[j]);
l = now + 1;
}
mx = max(a[i], mx);
}
}
// for(int i = 1; i <= n; ++i)if(a[i] == inf)printf("nan "); else printf("%d ",a[i]);
printf("\n");
}
int main(){
int t; scanf("%d",&t);
for(int i = 1; i <= t; ++i)solve();
return 0;
}
C. 混乱邪恶
奇妙构造
题解讲的很好,我就不废话了
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1000005;
int n, m, a[maxn], now[maxn << 2 | 1];
int ans[maxn], id[maxn];
int cnt;
struct node{int idx, idy, val;}d[maxn << 2 | 1];
struct note{
int val, id;
friend bool operator < (const note &x, const note &y){
return x.val < y.val;
}
};
multiset<note>s;
queue<int>Q;
int main(){
cin >> n >> m;
for(int i = 1; i <= n; ++i)cin >> a[i];
for(int i = 1; i <= n; ++i)id[a[i]] = i;
sort(a + 1, a + n + 1);
int p = 0;
for(int i = n; i >= 1; i -= 2){
d[++p].val = a[i] - a[i - 1];
d[p].idx = a[i]; d[p].idy = a[i - 1];
}
for(int i = 1; i <= p; ++i)s.insert({d[i].val, i});
int q = p;
for(int i = 1; i < p; ++i){
auto be = s.begin(), en = --s.end();
d[++q].idx =(*en).id;
d[q].idy = (*be).id;
d[q].val = (*en).val - (*be).val;
s.erase(be); s.erase(en);
s.insert({d[q].val, q});
}
int root = (*s.begin()).id;
now[root] = 1; Q.push(root);
while(!Q.empty()){
int x = Q.front(); Q.pop();
if(x <= p)continue;
now[d[x].idx] = now[x];
now[d[x].idy] = -now[x];
Q.push(d[x].idx);
Q.push(d[x].idy);
}
for(int i = 1; i <= p; ++i)ans[id[d[i].idx]] = now[i], ans[id[d[i].idy]] = -now[i];
printf("NP-Hard solved\n");
for(int i = 1; i <= n; ++i)printf("%d ",ans[i]);
return 0;
}
D. 校门外歪脖树上的鸽子
褐完了,,,,
学长的写法非常优雅
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read(){
int x = 0; char c = getchar();
while(c < '0' || c > '9') c = getchar();
do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
return x;
}
const int maxn = 4e5 + 10;
#define int long long
int n, m, ch[maxn][2];
int fa[maxn], dep[maxn], size[maxn], top[maxn], id[maxn], vis[maxn], son[maxn], root;
void dfs1(int x){
if(!ch[x][0] && !ch[x][1])size[x] = 1;
for(int i = 0; i <= 1; ++i){
int v = ch[x][i];
if(!v)continue;
fa[v] = x; dep[v] = dep[x] + 1;
dfs1(v); size[x] += size[v];
son[x] = size[son[x]] > size[v] ? son[x] : v;
}
}
int tim, dfn[maxn];
struct tree{
int build[maxn];
struct node{ll tag, val, size;}t[maxn << 2 | 1];
void push_up(int x){
t[x].val = t[x << 1].val + t[x << 1 | 1].val;
}
void upd(int x, int val){
t[x].val += t[x].size * val;
t[x].tag += val;
}
void push_down(int x){
upd(x << 1, t[x].tag);
upd(x << 1 | 1, t[x].tag);
t[x].tag = 0;
}
void built(int x, int l, int r){
if(l == r){
t[x].size = build[l];
return;
}
int mid = (l + r) >> 1;
built(x << 1, l, mid);
built(x << 1 | 1, mid + 1, r);
push_up(x);
t[x].size = t[x << 1].size + t[x << 1 | 1].size;
}
void modify(int x, int l, int r, int L, int R, ll val){
if(L > R)return;
if(L <= l && r <= R){
upd(x, val);
return;
}
int mid = (l + r) >> 1;
if(t[x].tag)push_down(x);
if(L <= mid)modify(x << 1, l, mid, L, R, val);
if(R > mid)modify(x << 1 | 1, mid + 1, r, L, R, val);
push_up(x);
}
ll query(int x, int l, int r, int L, int R){
if(L <= l && r <= R)return t[x].val;
if(t[x].tag)push_down(x);
int mid = (l + r) >> 1;
ll ans = 0;
if(L <= mid)ans += query(x << 1, l, mid , L, R);
if(R > mid)ans += query(x << 1 | 1, mid + 1, r, L ,R);
return ans;
}
}L, R;
void dfs2(int x, int tp){
top[x] = tp; dfn[x] = ++tim;
if(son[x])dfs2(son[x], tp);
for(int i = 0; i < 2; ++i)if(ch[x][i] && ch[x][i] != son[x])dfs2(ch[x][i], ch[x][i]);
R.build[dfn[ch[x][1]]] = size[ch[x][0]];
L.build[dfn[ch[x][0]]] = size[ch[x][1]];
}
void update(int l, int r, int val){
l = id[l - 1], r = id[r + 1];
int lasl = l, lasr = r;
while(top[l] != top[r]){
if(dep[top[l]] < dep[top[r]]){
R.modify(1, 1, tim, dfn[top[r]], dfn[r], val);
lasr = top[r]; r = fa[top[r]];
}else{
L.modify(1, 1, tim, dfn[top[l]], dfn[l], val);
lasl = top[l]; l = fa[top[l]];
}
}
if(dep[l] < dep[r]){
R.modify(1, 1, tim, dfn[l] + 2, dfn[r], val);
L.modify(1, 1, tim, dfn[lasl], dfn[lasl], -val);
}else{
L.modify(1, 1, tim, dfn[r] + 2, dfn[l], val);
R.modify(1, 1, tim, dfn[lasr], dfn[lasr], -val);
}
}
ll query(int l, int r){
l = id[l - 1], r = id[r + 1];
int lasl = l, lasr = r;
ll ans = 0;
while(top[l] != top[r]){
if(dep[top[l]] < dep[top[r]]){
ans += R.query(1, 1, tim, dfn[top[r]], dfn[r]);
lasr = top[r]; r = fa[top[r]];
}else{
ans += L.query(1, 1, tim, dfn[top[l]], dfn[l]);
lasl = top[l]; l = fa[top[l]];
}
}
if(dep[l] < dep[r]){
ans += R.query(1, 1, tim, dfn[l] + 2, dfn[r]) - L.query(1, 1, tim, dfn[lasl], dfn[lasl]);
}else{
ans += L.query(1, 1, tim, dfn[r] + 2, dfn[l]) - R.query(1, 1, tim, dfn[lasr], dfn[lasr]);
}
return ans;
}
signed main(){
n = read(), m = read();
for(int i = 1; i < n; ++i){
vis[ch[i + n][0] = read()] = true;
vis[ch[i + n][1] = read()] = true;
}
for(int i = 1; i <= n + n; ++i)if(!vis[i]){root = i; break;}
ch[n + n + 1][0] = n + n;
ch[n + n + 1][1] = root;
ch[n + n + 3][0] = n + n + 1;
ch[n + n + 3][1] = n + n + 2;
for(int i = 1; i <= n; ++i)id[i] = i;
id[0] = n + n; id[n + 1] = n + n + 2;
root = n + n + 3;
dfs1(root); dfs2(root, root);
L.built(1, 1, tim); R.built(1, 1, tim);
for(int i = 1; i <= m; ++i){
int opt = read(), l = read(), r = read();
if(opt & 1){
int val = read(); update(l, r, val);
}else printf("%lld\n",query(l, r));
}
return 0;
}