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; }
下面的就不需要那么麻烦了,我们根据左右的特点可以直接写出他的顺序。
如果往左,那么就是切掉右边,那么现在的值就是当前最大的。
如果往右,就是切掉左边,值就是当前最小的。
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; }
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; }