A。主要考虑是否有0,分开判断即可。
int a[Max];
int main()
{
int n , k;
cin >> n >> k;
int sign = 0 ;
int haszero = 0;
for (int i = 0 ; i < n ;i ++){
scanf("%d",&a[i]);
if(!a[i])haszero = 1;
if(a[i] < 0)sign ++;
}
sort(a, a + n);
if(k <= sign)
{
int ans = 0;
for (int i = 0 ;i < n ;i ++)
{
if(k)
{
ans += abs(a[i]);
k --;
}
else ans += a[i];
}
cout <<ans <<endl;
}
else
{
int ans = 0 ;
for (int i = 0 ;i < n ;i ++)ans += abs(a[i]);
if(haszero)
cout <<ans <<endl;
else
{
int min = inf;
for (int i = 0 ;i < n ;i ++)if(min > abs(a[i])&& a[i] != 0)min = abs(a[i]);
k -= sign ;
if(k&1)
ans -= min * 2;
cout <<ans <<endl;
}
}
return 0;
}
B。根据题意,肯定是选择容量最小的折扣,这样拿的免费物品最多。
int a[Max];
int vis[Max];
int main()
{
int n , m ;
cin >> n ;
for (int i = 0 ; i < n ; i ++)cin >> vis[i] ;
cin >> m ;
for (int i = 0 ; i < m ; i ++)cin >>a[i] ;
sort(a , a + m );
sort(vis , vis + n );
int ans = 0 ;
int free = 0 ;
int nofree = vis[0];//容量最小的
for (int i = m - 1 ;i >= 0 ;i --)
{
if(free > 0)
{
free -- ;
nofree = vis[0];
continue;
}
nofree -- ;
if(!nofree)free = 2;
ans += a[i];
}
cout << ans << endl;
}
C。dp,详见鸨神
http://blog.csdn.net/cugbbaoge/article/details/8753331
D。没啥陷阱
int a[100];
int main()
{
int n , k ;
cin >> n >> k;
for (int i = 0 ;i < n ;i ++)scanf("%d",a + i);
sort(a , a + n);
if(k > n )
cout << -1 <<endl;
else if(k == n)
cout <<0 <<" "<<0<<endl;
else
{
cout <<a[n - k] <<" "<< 0 <<endl;
}
}
E。给你n个节点,组成一个环,然后一共有2*n条路,这些路是相邻的两个点,也可以是中间隔着另外一点的两个点。
假设换是这样的a -> b- > c ->d -> e -> a。那么给你的路可能是a -> b,a->c, a -> e,a -> d。
一共是2*n条路。
然后求出任意一种环的顺序。
参考了CF上的代码。思路见注释。
vector<int>qq[Max*100];
int n ;
vector<int>ans;
bool vv[Max*100];
void dfs1()
{
int l = ans.size();
int x = ans[l - 1 ];
int y = ans[l - 2 ];//取两个点。
for (int i = 0 ; i < 4; i ++)
{
for (int j = 0 ; j < 4 ; j ++)
{
int px = qq[x][i];
int py = qq[y][j];
if(px == py && !vv[py])//这个判断非常巧妙,要是满足,则继续递归。如果满足这个条件,则x 与px直接相连,y与px直接相连,x 与 y隔着px相连。三者的关系就都满足了
{
vv[py] = 1 ;
ans.pb(py);
if(ans.size() < n )
{
dfs1();
}
else
{
// cout <<1;
for (int i = 0 ; i < ans.size(); i ++)
cout <<ans[i] + 1 <<" ";
exit(0);
}
vv[py] = 0 ;
ans.pop_back();
}
}
}
}
int main()
{
cin >> n ;
for (int i = 0 ; i < n * 2 ; i ++)
{
int a , b ;
cin >> a >> b;
a-- , b --;
qq[a].push_back(b);
qq[b].push_back(a);
} for (int i = 0 ; i < n ; i ++)
if(qq[i].size() < 4)//任意点度数小于4,则输出-1
{
cout << -1 <<endl;
return 0;
}
for (int i = 0 ; i < 4 ; i ++)//枚举和节点0相连的两点。
{
for (int j = 0 ; j < 4 ; j ++)
{
if(i != j)
{
int px = qq[0][i];
int py = qq[0][j];
vv[px] = 1 ;
vv[py] = 1;
ans.pb(px);
ans.pb(py);
dfs1();//从这两点出发开始找
vv[px] = 0;
vv[py] = 0;
ans.pop_back();
ans.pop_back();
}
}
}
cout << -1 <<endl;
return 0;
}
F。题意:给你一幅图,求出长度大于k的环,并输出编号。
思路:从节点0开始搜,记录每个节点的深度,如果出现某个点已被访问(vis[n] != 0)那么证明这条链中有一个节点收尾相接了,即成环了。
那么他们的深度差就是环的长度。
看代码还是好理解的。
vector<int>q[Max*100];
int deep = 0 ;
int vv[Max*100];
int pre[Max*100];
int n , m , k;
bool flag = 0;
void dfs(int nn)
{
for (int i = 0 ; i < q[nn].size(); i ++)
{
if(!vv[q[nn][i]])
{
vv[q[nn][i]] = vv[nn] + 1;
pre[q[nn][i]] = nn;//记录前驱.
dfs(q[nn][i]);
}
else if(vv[nn] - vv[q[nn][i]] + 1 > k)
{
int kk = nn;
cout <<vv[nn] - vv[q[nn][i]] + 1 <<endl;
for ( ; kk != q[nn][i]; kk = pre[kk])
cout << kk + 1 <<" ";
cout <<q[nn][i] + 1 <<endl;
exit(0);
}
else
continue;
}
return ;
}
int main()
{
cin >> n >> m >> k;
memset(vv,0,sizeof(vv));
for (int i = 0 ; i < m ; i ++)
{
int a , b ;
cin >> a >> b;
a--,b--;
q[a].push_back(b);
q[b].push_back(a);
}
dfs(0);
return 0;
}
G。模拟即可
int a[100005];
int main()
{
int n ;
cin >> n;
for (int i = 0 ;i < n ;i ++)scanf("%d",a + i);
int h = 0;
ll ans = 0;
for (int i = 0 ;i < n ;i ++)
{
ans += a[i] - h;//go to top
ans ++ ;//eat
if(i == n - 1)
break;
if(a[i + 1] <a[i] )
ans += a[i] - a[i + 1];
ans ++ ;//jump
h = min(a[i],a[i + 1]);//updata the height
}
cout << ans <<endl;
}
H。也可以直接模拟做,记录 num值,最后排序输出。不过不知道精度够不够。
下面的就不需要那么麻烦了,我们根据左右的特点可以直接写出他的顺序。
如果往左,那么就是切掉右边,那么现在的值就是当前最大的。
如果往右,就是切掉左边,值就是当前最小的。
string a;
int b[10000005];
int main()
{
cin >> a;
int l = a.length();
int lt = 0 ,rt = l - 1;
for (int i = 0 ; i < l ; i ++)
{
if(a[i] == 'l')b[rt -- ] = i ;//cut the right , this is the RTth big num
else b[lt ++ ] = i;//same
}
for (int i = 0 ; i < l ; i ++)cout <<b[i] + 1 <<endl;
}
I。这题也很巧妙。不需要判断两个数是否互质,直接将每个数的因子拿出来,进行dp.
int a[1000005];
int dp[1000005];
int b[1000005];
int main()
{
int n ;
cin >> n ;
int ans = 0 ;
int num = 1;
for (int i = 0 ; i < n ; i ++ )
{
scanf("%d",a + i );
dp[i] = 0;
}
for (int i = 0 ;i < n ;i ++)//a[i]是递增输入的
{
for (int j = 1 ;j * j <= a[i] ;j ++)
{
if(a[i] % j == 0)//找a[i]的因子
{
int x = j;
int y = a[i] / j;
if(x > 1)dp[i] = max(max(dp[i], b[x]),b[y]);//b[x]记录的是0 - i之间,有因子x且组成的最长序列。同理b[y]。
}
}
for (int j = 1 ;j * j <= a[i] ;j ++)
{
if(a[i] % j == 0)//更新b[x],b[y]序列
{
int x= j ;
int y = a[i] / j;
if(x > 1)
b[x] = max(b[x], dp[i] + 1);
if(y != x)
b[y] = max(b[y], dp[i] + 1);
}
}
}
for (int i = 0 ;i < n ;i ++)ans = max(ans, dp[i]);
cout << ans + 1 <<endl;
return 0;
}