8.20 模拟赛
\(100+80+40+50\) \(rk6\)
T1
一个非常暴力的\(dp\) 我们枚举\(3*3\)的状态并进行转移即可
注意上一层节点的状态只能转移一次
本地测试\(std\)和下述代码均\(MLE\) 但教师机上可以\(AC\)
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define mid (l+r>>1)
#define inl inline
#define eb emplace_back
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
const int N = 1e7 + 5;
const int inf = 0x3f3f3f3f;
//char buf[1<<24] , *p1 , *p2;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
int n , f[N][4][4] , vis[4][4] , col[N];
char ch;
int get ( char ch )
{
if ( ch == 'R' ) return 1;
if ( ch == 'G' ) return 2;
if ( ch == 'B' ) return 3;
}
signed main ()
{
freopen ( "eliminate.in" , "r" , stdin );
freopen ( "eliminate.out" , "w" , stdout );
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
memset ( f , -0x3f , sizeof f );
ch = getchar();
while ( ch != EOF && ch != '\n' ) if ( ch != ' ' ) ++ n , col[n] = get(ch) , ch = getchar();
f[0][0][0] = 0;
for ( int k = 1 ; k <= n ; k ++ )
{
int now = col[k];
memset ( vis , 0 , sizeof vis );
for ( int i = 0 ; i <= 3 ; i ++ ) for ( int j = 0 ; j <= 3 ; j ++ ) f[k][i][j] = max ( f[k][i][j] , f[k-1][i][j] ); //��Ⱦ
if ( !vis[0][0] ) f[k][now][0] = max ( f[k][now][0] , f[k-1][0][0] ) , vis[0][0] = 1;//st1
for ( int i = 1 ; i <= 3 ; i ++ ) if ( !vis[i][0] ) f[k][i][now] = max ( f[k][i][now] , f[k-1][i][0] ) , vis[i][0] = 1;//st2
for ( int i = 1 ; i <= 3 ; i ++ ) if ( !vis[now][now] ) f[k][i][0] = max ( f[k][i][0] , f[k-1][now][now] + 1 );//st3
vis[now][now] = 1;
for ( int i = 1 ; i <= 3 ; i ++ )//st4
for ( int j = 1 ; j <= 3 ; j ++ )
if ( i != j && i != now && j != now )
{
if ( !vis[i][j] )
for ( int p = 1 ; p <= 3 ; p ++ )
for ( int q = 1 ; q <= 3 ; q ++ ) f[k][p][q] = max ( f[k][p][q] , f[k-1][i][j] );
vis[i][j] = 1;
}
for ( int i = 1 ; i <= 3 ; i ++ )//st5
for ( int j = 1 ; j <= 3 ; j ++ )
if ( ( i == j && i != now ) || ( i == now && i != j ) || ( j == now && i != j ) )
if ( !vis[i][j] ) f[k][j][now] = max ( f[k][j][now] , f[k-1][i][j] ) , vis[i][j] = 1;
}
// for ( int i = 1 ; i <= n ; i ++ , cout.put(endl) )
// for ( int j = 1 ; j <= 3 ; j ++ , cout.put(endl) )
// for ( int k = 1 ; k <= 3 ; k ++ ) cout << f[i][j][k] << ' ';
int ans = -inf;
for ( int i = 0 ; i <= 3 ; i ++ ) for ( int j = 0 ; j <= 3 ; j ++ ) ans = max ( ans , f[n][i][j] );
cout << ans << endl;
return 0;
}
T2
签到题 但是被诈骗了() 需要判空
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define mid (l+r>>1)
#define inl inline
#define eb emplace_back
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
#define int long long
const int N = 1e5 + 5;
//char buf[1<<24] , *p1 , *p2;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
#define getchar() cin.get();
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f ;
}
int n;
priority_queue<int> q;
int sta[N] , top;
int que[N] , head = 1 , tail = 0;
int ispri = 1 , issta = 1 , isque = 1;
signed main ()
{
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
freopen ( "guess.in" , "r" , stdin );
freopen ( "guess.out" , "w" , stdout );
n = read();
for ( int i = 1 ; i <= n ; i ++ )
{
int op = read() , val = read();
if ( op == 1 ) sta[++top] = val , que[++tail] = val , q.push(val);
else
{
if ( head > tail ) { issta = isque = ispri = 0; continue; }
if ( sta[top] != val ) issta = 0;
if ( que[head] != val ) isque = 0;
if ( q.top() != val ) ispri = 0;
head++ , top-- , q.pop();
}
}
cout << (issta?"YES":"NO") << endl;
cout << (isque?"YES":"NO") << endl;
cout << (ispri?"YES":"NO") << endl;
return 0;
}
T3
\(n^3\)暴力显然
观察到更新的区间是一个轮廓线状的东西() 可以用\(bit\)来维护(?
\(40pts:\)
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define mid (l+r>>1)
#define inl inline
#define eb emplace_back
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
#define int long long
const int N = 2e3 + 5;
//char buf[1<<24] , *p1 , *p2;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
#define getchar() cin.get();
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f ;
}
int n , f[N][N] , a[N][N] , ans;
char ch;
signed main ()
{
freopen ( "run.in" , "r" , stdin );
freopen ( "run.out" , "w" , stdout );
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
n = read();
for ( int i = 1 ; i <= n ; i ++ ) for ( int j = 1 ; j <= n ; j ++ ) a[i][j] = read();
for ( int i = 1 ; i <= n ; i ++ ) for ( int j = 1 ; j <= n ; j ++ ) f[i][j] = a[i][j] + max ( f[i-1][j] , f[i][j-1] );
for ( int i = 1 ; i <= n ; i ++ ) for ( int j = 1 ; j <= n ; j ++ ) ans += f[i][j];
cout << ans << endl;
for ( int k = 1 , x , y ; k <= n ; k ++ )
{
cin >> ch; x = read() , y = read();
if ( ch == 'U' ) a[x][y] ++; else a[x][y] --;
for ( int i = x ; i <= n ; i ++ ) for ( int j = y ; j <= n ; j ++ )
{
int temp = f[i][j];
f[i][j] = a[i][j] + max ( f[i-1][j] , f[i][j-1] );
ans += f[i][j] - temp;
}
cout << ans << endl;
}
return 0;
}
T4
树上差分+树剖\(LCA\)可以有\(O(n^2logn)\)的优秀复杂度
应该得\(30pts\) 但是得了\(50pts\) 赢!
正解是淀粉质(\(noip\)算法?
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define mid (l+r>>1)
#define inl inline
#define eb emplace_back
#define ls p<<1
#define rs p<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
#define pii pair<int,int>
const int N = 1e5 + 5;
const int inf = 0x3f3f3f3f;
//char buf[1<<24] , *p1 , *p2;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<24,stdin),p1==p2)?EOF:*p1++)
#define getchar() cin.get();
int read()
{
int x = 0 , f = 1;
char ch = getchar();
while ( !isdigit(ch) ) { if ( ch == '-' ) f = -1; ch = getchar(); }
while ( isdigit(ch) ) { x = ( x << 1 ) + ( x << 3 ) + ( ch ^ 48 ); ch = getchar(); }
return x * f ;
}
int n , buc[3][N] , a[N] , ans;
string s;
int get ( char ch )
{
if ( ch == 'a' ) return 0;
if ( ch == 'b' ) return 1;
if ( ch == 'c' ) return 2;
}
vector<int> e[N];
inl void add ( int u , int v ) { e[u].eb(v); }
int fa[N] , sz[N] , son[N] , dep[N];
int top[N] , rev[N] , pos[N] , timer;
struct LCA
{
void dfs1 ( int u , int f )
{
dep[u] = dep[fa[u]=f] + 1 , sz[u] = 1;
for ( auto v : e[u] )
if ( v ^ f )
{
dfs1 ( v , u );
sz[u] += sz[v];
if ( sz[son[u]] < sz[v] ) son[u] = v;
}
}
void dfs2 ( int u , int tp )
{
top[u] = tp , pos[u] = ++timer , rev[timer] = u;
if ( son[u] ) dfs2 ( son[u] , tp );
for ( auto v : e[u] ) if ( v ^ son[u] && v ^ fa[u] ) dfs2 ( v , v );
}
int lca ( int u , int v )
{
while ( top[u] != top[v] )
{
if ( dep[top[u]] < dep[top[v]] ) swap ( u , v );
u = fa[top[u]];
}
if ( dep[u] < dep[v] ) swap ( u , v );
return v;
}
}L;
void dfs ( int u , int f )
{
++ buc[a[u]][u];
for ( int i = 0 ; i < 3 ; i ++ ) buc[i][u] += buc[i][f];
for ( auto v : e[u] )
if ( v ^ f ) dfs ( v , u );
}
signed main ()
{
freopen ( "tree.in" , "r" , stdin );
freopen ( "tree.out" , "w" , stdout );
ios::sync_with_stdio(false);
cin.tie(0) , cout.tie(0);
n = read();
cin >> s;
for ( int i = 1 ; i <= n ; i ++ ) a[i] = get(s[i-1]);
for ( int i = 1 , u , v ; i < n ; i ++ ) u = read() , v = read() , add ( u , v ) , add ( v , u );
L.dfs1 ( 1 , 0 ) , L.dfs2 ( 1 , 1 );
dfs ( 1 , 0 );
for ( int i = 1 ; i <= n ; i ++ )
for ( int j = i ; j <= n ; j ++ )
{
int aa = buc[0][i] + buc[0][j] - buc[0][L.lca(i,j)] - buc[0][fa[L.lca(i,j)]];
int bb = buc[1][i] + buc[1][j] - buc[1][L.lca(i,j)] - buc[1][fa[L.lca(i,j)]];
int cc = buc[2][i] + buc[2][j] - buc[2][L.lca(i,j)] - buc[2][fa[L.lca(i,j)]];
if ( aa == bb && bb == cc && aa == cc ) ++ans;
}
cout << ans << endl;
return 0;
}