C
思路:模拟处理一下。
Code:
#include <bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int MOD = 1e9+7;
const int AX = 3e5+66;
int a[AX];
int b[AX];
char s[AX];
int main(){
scanf("%s",s+1);
int len = strlen(s+1);
int m = len / 2;
LL la = 0 , lb = 0;
for( int i = 1 ; i <= m ; i++ ){
a[i] = s[i] - 'A';
la += s[i] - 'A';
}
for( int i = m + 1 ; i <= len ; i++ ){
b[i-m] = s[i]-'A';
lb += s[i] - 'A';
}
for( int i = 1 ; i <= m ; i++ ){
a[i] = ( a[i] + la ) % 26;
b[i] = ( b[i] + lb ) % 26;
}
for(int i = 1 ; i <= m ;i++ ){
a[i] = ( a[i] + b[i] ) % 26;
}
for(int i = 1 ; i <= m ; i++ ){
printf("%c",a[i]+'A');
}printf("\n");
return 0 ;
}
D
题意:鸡蛋开始在0,后面会有让鸡蛋顺时针,逆时针传x距离的操作,还有撤销最后x个操作 的 操作。问最后鸡蛋在哪。
思路:就是统计下,比较符合栈定义,然后就是不知道我计算数有什么bug,一直错,换成stringstream流就行了。。。
Code:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
int main(){
stringstream ss;
stack<LL> s;
LL n, k, x;
string op;
cin >> n >> k;
for ( int i = 0; i < k ; i++ ){
cin >> op;
if (op[0] == 'u'){
cin >> x ;
for ( int j = 0; j < x; j++ )
s.pop();
}
else{
ss.clear();
ss << op;
ss >> x;
s.push(x);
}
}
LL ans = 0;
while (!s.empty()){
ans += s.top();
s.pop();
}
cout << (ans % n + n) % n << endl;
return 0;
}
题意:有两种关系,一种是x是y的子类,一种是x包含y。符合传递关系,给m个询问,判断询问对与否。
思路:直接dfs搜,主要是确定好传递关系怎么搜才不会漏掉情况,子类这个关系好解决,就是简单的找每个点然后搜到底。
包含关系主要分这三个方面:
一. x包含y,z包含x,那么z包含y
二. x包含y,y是z的子类,那么x包含z
三. x包含y,z是x子类,那么z包含y
然后对每个点的包含关系开始搜,保证x包含y,然后在搜索中找满足第二个条件的去标记。
Code:
#include <bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int MOD = 1e9+7;
const int AX = 1e4+66;
const char s1[] = "is-a";
bool res ;
char s[AX];
string a , b ;
std::vector<int> v_has[AX];
std::vector<int> v_has_inv[AX];
std::vector<int> v_is[AX];
std::vector<int> v_is_inv[AX];
map<string,int>mp;
bool is[AX][AX];
bool has[AX][AX];
bool vis[AX];
void dfs_is( int x , int pre ){
is[pre][x] = true;
v_is[pre].push_back(x);
v_is_inv[x].push_back(pre);
vis[x] = true;
for( int i = 0 ; i < v_is[x].size() ; i++ ){
if( !vis[v_is[x][i]] ){
dfs_is( v_is[x][i] , pre );
}
}
}
void dfs_has( int x , int y ){
//z has x , x has y
for( int i1 = 0 ; i1 < v_has_inv[x].size() ; i1++ ){
if( !has[ v_has_inv[x][i1] ][y] ){
has[ v_has_inv[x][i1] ][y] = true;
dfs_has( v_has_inv[x][i1] , y );
}
}
//x has y y is z
for( int i2 = 0 ; i2 < v_is[y].size() ; i2++ ){
if( !has[x][ v_is[y][i2] ] ){
has[x][v_is[y][i2]] = true ;
dfs_has( x , v_is[y][i2] );
}
}
//z is x , x has y
for( int i3 = 0 ; i3 < v_is_inv[x].size() ; i3 ++ ){
if( !has[ v_is_inv[x][i3] ][y] ){
has[ v_is_inv[x][i3] ][y] = true;
dfs_has( v_is_inv[x][i3] , y );
}
}
}
int main(){
ios_base::sync_with_stdio(false); cin.tie(0) ; cout.tie(0);
int n , m ;
cin >> n >> m ;
int tot = 0;
for( int i = 0 ; i < n ; i++ ){
cin >> a >> s >> b ;
if( !mp[a] ) mp[a] = ++tot;
if( !mp[b] ) mp[b] = ++tot;
if( !strcmp( s , s1 ) ) { v_is[mp[a]].push_back(mp[b]); v_is_inv[mp[b]].push_back(mp[a]); }
else { v_has[mp[a]].push_back(mp[b]); v_has_inv[mp[b]].push_back(mp[a]) ; }
}
for( int i = 1 ; i <= tot ; i++ ){
memset( vis, false , sizeof(vis) );
dfs_is( i , i );
}
for( int i = 1 ; i <= tot ; i++ ){
for( int j = 0 ; j < v_has[i].size( ) ; j ++ ){
dfs_has( i , v_has[i][j] );
}
}
int Case = 0 ;
while( m-- ){
cout << "Query " << ++Case << ": " ;
cin >> a >> s >> b;
if( !strcmp( s , s1 ) ){
cout << ( is[mp[a]][mp[b]] ? "true\n" : "false\n" );
}else{
cout << ( has[mp[a]][mp[b]] ? "true\n" : "false\n" );
}
}
return 0 ;
}
F
题意:额,题目看很久没看懂,看了下ac代码,就是给一个树,求去掉一个节点能够得到的最大不连通的数对,输出这个数以及你添加一条边后仍然不连通的数对。
思路:先求各个节点子树的节点数,则与每个节点相连的这些数目相乘加和就是这个节点断开时不连通的数对,添加边肯定添加在与这个节点相连的节点最多的两个子树之间。
Code:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int AX = 1e4+66;
std::vector<int>G[AX];
int num[AX];
int dfn[AX];
int index ;
int dfs( int x , int fa ){
num[x] = 1 ;
dfn[x] = ++index;
for( int i = 0 ; i < G[x].size() ; i++ ){
if( fa == G[x][i] ) continue;
num[x] += dfs( G[x][i] , x );
}
return num[x];
}
int main(){
int n ;
scanf("%d",&n);
int index = 0 ;
memset( num , 0 , sizeof(num) );
memset( dfn , 0 , sizeof(dfn) );
int u , v ;
for( int i = 0 ; i < n ; i++ ){
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs( 0 , -1 ) ;
LL tmp[AX];
LL res = 0 ;
LL res2 = 0 ;
std::vector<int> vv;
for( int i = 0 ; i <= n ; i++ ){
vv.clear();
LL t = 0 ;
LL tmp = 0 ;
for( int j = 0 ; j < G[i].size() ; j++ ){
int v = G[i][j];
if( dfn[v] < dfn[i] ) continue;
tmp += t * num[v];
t += num[v];
vv.push_back(num[v]);
}
tmp += t * ( n - t );
vv.push_back( n - t );
sort( vv.begin() , vv.end() );
if( res < tmp ){
res = tmp ;
res2 = (LL)vv[vv.size()-1] * vv[vv.size()-2];
}
}
printf("%lld %lld\n",res , res - res2);
return 0 ;
}
G
题意:
思路:动态规划,dp[i][j]表示到第i个连续吃 j - 1 道菜,加上i就是j道(也可以理解为到第i道菜能吃的卡路里是 m * (2/3) ^ j 时 )可以获得的卡路里。
那么i有三种情况讨论:
1. 前面停了2次,dp[i][j] = max( dp[i-3][j] ) + min(m,a[i])
2. 前面停了1次, dp[i][j] = max( dp[i-2][j] ) + min( a[i] , i-2处的食量)
3. 前面没有停 dp[i][j] = max( dp[i-1][j-1] ) + min ( a[i] , j-1处的食量*2/3)
Code:
#include <bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int MOD = 1e9+7;
const int AX = 1e2+6;
int dp[AX][AX];
int sum[AX];
int a[AX];
int n , m ;
int cal( int mi ){
int ans = m ;
for( int i = 0 ; i < mi ; i++ ){
ans = ans * 2 / 3 ;
}
return ans ;
}
int main(){
scanf("%d%d",&n,&m);
memset( dp , 0 , sizeof(dp) );
int t = m ;
for( int i = 1 ; i <= n ; i++ ){
scanf("%d",&a[i]);
sum[i] = sum[i-1] + min( a[i] , t );
t = t * 2 / 3 ;
}
for( int i = 1 ; i <= n ; i++ ){
dp[i][i-1] = sum[i];
}
for( int i = 1 ; i <= n ; i++ ){
for( int j = 0 ; j < i ; j++ ){
if( j ) dp[i][j] = max( dp[i][j] , dp[i-1][j-1] + min( a[i] , cal(j) ) );
if( i >= 2 ) dp[i][j] = max( dp[i-2][j] + min( a[i] , cal(j) ) , dp[i][j] );
if( i >= 3 ) dp[i][0] = max( dp[i-3][j] + min( a[i] , m ) , dp[i][0] );
}
}
int res = -1 ;
for( int j = 0 ; j < n ; j++ ){
res = max( dp[n][j] , res );
}
printf("%d\n",res);
return 0 ;
}
H
思路:基础搜索,连通块。。
Code:
#include <bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int MOD = 1e9+7;
const int AX = 105+6;
char G[AX][AX];
int vis[AX][AX];
int m , n ;
int dir[8][2] ={
{1,0},
{0,1},
{-1,0},
{0,-1},
{1,-1},
{-1,1},
{-1,-1},
{1,1}
};
void dfs( int x , int y ){
vis[x][y] = 1 ;
for( int i = 0 ; i < 8 ; i++ ){
int xx = x + dir[i][0];
int yy = y + dir[i][1];
if( xx >= 0 && xx < m && yy >= 0 && yy < n && !vis[xx][yy] && G[xx][yy] == '#' ){
dfs(xx,yy);
}
}
}
int main(){
scanf("%d%d",&m,&n);
for( int i = 0 ; i < m ; i++ ){
scanf("%s",&G[i]);
}
memset( vis , 0 , sizeof(vis) );
int res = 0 ;
for(int i = 0 ; i < m ; i++ ){
for( int j = 0 ; j < n ; j++ ){
if( !vis[i][j] && G[i][j] == '#' ){
dfs(i,j);
res ++;
}
}
}
printf("%d\n",res);
return 0 ;
}