题目链接:
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=89012#overview
密码:
654
1.Case of the Zeros and Ones
题目链接:
http://codeforces.com/problemset/problem/556/A
解题思路:
官方题解:
If there still exist at least one 0 and at least one 1 in the string then there obviously exists either substring 01 or substring 10 (or both) and we can remove it. The order in which we remove substrings is unimportant: in any case we will make min(#zeros, #ones) such operations. Thus the answer is #ones + #zeros - 2min(#ones, #zeros) = |#ones - #zeros|.
AC代码:
#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
using namespace std;
int main(){
int n;
string str;
while(cin>>n){
cin>>str;
int l = str.size();
int sum1 = 0,sum2 = 0;
for(int i = 0; i < l; i++){
if(str[i] == '0')
sum1++;
else if(str[i] == '1')
sum2++;
}
cout<<abs(sum1-sum2)<<endl;
//printf("%d\n",abs(sum1-sum2));
}
return 0;
}
2.Divisors
题目链接:
http://poj.org/problem?id=2992
解题思路:
http://blog.youkuaiyun.com/piaocoder/article/details/47955351
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
typedef long long ll;
vector<int> v;
int prime[500];
int a[450][450];
int unprime[500],nprime;
int sum[500];
void getprime(){
nprime = 0;
memset(unprime,0,sizeof(unprime));
for(int i = 2; i < 500; i++){
for(int j = i*i; j < 500; j+=i)
unprime[j] = 1;
}
for(int i = 2; i < 500; i++){
if(!unprime[i])
prime[nprime++] = i;
}
}
void div(int x){
v.clear();
int t = x;
for(int i = 0; i < nprime && prime[i]*prime[i] <= x; i++){
while(t % prime[i] == 0){
v.push_back(prime[i]);
t /= prime[i];
}
if(t == 1)
break;
}
if(t > 1)
v.push_back(t);
}
void solve(){
memset(a,0,sizeof(a));
for(int i = 2; i <= 431; i++){
memcpy(a[i],a[i-1],sizeof(a[i]));
div(i);
for(int j = 0; j < v.size(); j++)
a[i][v[j]]++;
}
}
int main(){
getprime();
solve();
int n,k;
while(~scanf("%d%d",&n,&k)){
memset(sum,0,sizeof(sum));
for(int i = 1; i <= 431; i++)
sum[i] += a[n][i]-a[k][i]-a[n-k][i];
ll ans = 1;
for(int i = 2; i <= 431; i++)
ans *= (sum[i]+1);
printf("%lld\n",ans);
}
return 0;
}
3.SKYLINE
题目链接:
解题思路:
http://blog.youkuaiyun.com/piaocoder/article/details/47958199
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 100005;
const int NN = 100000;
struct node{
int l,r,maxn;
int lazy;
}tree[N<<2];
int sum;
void build(int id,int l,int r){
tree[id].l = l;
tree[id].r = r;
tree[id].maxn = 0;
tree[id].lazy = 1;
if(l == r)
return ;
int mid = (l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
}
void pushdown(int id){
if(tree[id].lazy){
tree[id<<1].maxn = tree[id<<1|1].maxn = tree[id].maxn;
tree[id].lazy = 0;
}
}
void update(int id, int l, int r, int h){
if (tree[id].l == l && tree[id].r == r && tree[id].lazy){
if (h > tree[id].maxn)
tree[id].maxn = h;
return;
}
pushdown(id);
int mid = (tree[id].l+tree[id].r)>>1;
if (r <= mid)
update(id<<1,l,r,h);
else if (l > mid)
update(id<<1|1,l,r,h);
else {
update(id<<1,l,mid,h);
update(id<<1|1,mid+1,r,h);
}
tree[id].maxn = max(tree[id<<1].maxn,tree[id<<1|1].maxn);
}
int query(int id,int l,int r,int h){
if(tree[id].lazy){
if(tree[id].maxn <= h){
update(id,l,r,h);
return r-l+1;
}
else
return 0;
}
pushdown(id);
int mid = (tree[id].l+tree[id].r)>>1;
if (r <= mid)
return query(id<<1,l,r,h);
else if (l > mid)
return query(id<<1|1,l,r,h);
else
return query(id<<1,l,mid,h) + query(id<<1|1,mid+1,r,h);
tree[id].maxn = max(tree[id<<1].maxn,tree[id<<1|1].maxn);
}
int main(){
int T,n;
scanf("%d",&T);
while(scanf("%d",&n),n){
int ans = 0;
build(1,1,NN);
int l,r,h;
for(int i = 0; i < n; i++){
scanf("%d%d%d",&l,&r,&h);
r--;
sum = query(1,l,r,h);
ans += sum;
}
printf("%d\n",ans);
}
return 0;
}
4.Heavy Cargo
题目链接:
http://poj.org/problem?id=2263
解题思路:
一开始读错了题,想成了最大流,后来才发现,原来题意是这样的。。。
有n个点,m条路,每条路双向的,现在卡车从某点到另一点,卡车的承载无上限,但是马路的承载有上限,问卡车应该承载多少才不会压坏马路。
用dijkstra和floyd都可以做,求出最小负载中的最大值。。。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <map>
#include <algorithm>
#define INF 0xfffffff
using namespace std;
const int N = 210;
int n,m;
int edge[N][N];
map<string,int> mm;
int dis[N];
int vis[N];
int minn;
string str1,str2;
void dijkstra(int cur)
{
int i,j,next,MAX;
memset(vis,0,sizeof(vis));
for(i = 1; i <= n; i++)
dis[i] = edge[cur][i];
dis[cur] = 0;
for(i = 1; i <= n; i++)
{
MAX = 0;
for(j = 1; j <= n; j++)
if(!vis[j] && dis[j]>MAX)
MAX = dis[next=j];
vis[next] = 1;
for(j = 1; j<= n; j++)
if(!vis[j] && dis[j] < min(MAX,edge[next][j]))
dis[j] = min(MAX,edge[next][j]);
}
}
void floyd(){
for(int k = 1; k <= n; k++){
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
edge[i][j] = max(edge[i][j],min(edge[i][k],edge[k][j]));
}
}
}
}
int main(){
int t = 1;
while(scanf("%d%d",&n,&m),n+m){
mm.clear();
memset(edge,0,sizeof(edge));
int num;
int id = 1;
for(int i = 0; i < m; i++){
cin>>str1>>str2>>num;
if(!mm[str1])
mm[str1] = id++;
if(!mm[str2])
mm[str2] = id++;
edge[mm[str1]][mm[str2]] = edge[mm[str2]][mm[str1]] = num;
}
cin>>str1>>str2;
minn = INF;
//dijkstra(mm[str1]);
floyd();
printf("Scenario #%d\n",t++);
printf("%d tons\n\n",edge[mm[str1]][mm[str2]]);
}
return 0;
}
5.Kyoya and Photobooks
题目链接:
http://codeforces.com/problemset/problem/554/A
解题思路:
官方题解:
Solving this problem just requires us to simulate adding every character at every position at the string, and removing any duplicates. For instance, we can use a HashSet of Strings in Java to do this (a set in C++ or Python works as well).
Bonus: Prove that the number of ways is always (length of string + 1) * 25 + 1.
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
int main(){
string str;
while(cin>>str){
int l = str.size();
printf("%d\n",25*(l+1)+1);
}
return 0;
}
6.Best Cow Line
题目链接:
http://poj.org/problem?id=3617
解题思路:
http://blog.youkuaiyun.com/piaocoder/article/details/47425177
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
int main(){
int n;
while(~scanf("%d",&n)){
string str = "";
char x;
for(int i = 0; i < n; i++){
cin>>x;
str += x;
}
int l = 0,r = n-1;
int sum = 0;
while(l <= r){
bool flag;//表示是否取左边
for(int i = 0; l + i <= r; i++){
if(str[l+i] < str[r-i]){
flag = true;
break;
}
else if(str[l+i] > str[r-i]){
flag = false;
break;
}
}
if(flag)
putchar(str[l++]);
else
putchar(str[r--]);
sum++;
if(sum % 80 == 0){
printf("\n");
}
}
}
return 0;
}
7.Friends
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5305
解题思路:
http://blog.youkuaiyun.com/piaocoder/article/details/47657163
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n,m;
int a[30],b[30],cnt;
int sum[10],on[10],off[10];//sum记录每个点的度数,on记录每个点的online,off记录每个点的offline
bool judge(){
for(int i = 1; i <= n; i++){
if(on[i] != off[i])
return false;
}
return true;
}
void dfs(int cur){
if(cur == m+1){
if(judge()){
cnt++;
return;
}
}
int x = a[cur], y = b[cur];
if(on[x] < sum[x]/2 && on[y] < sum[y]/2){
on[x]++;
on[y]++;
dfs(cur+1);
on[x]--;
on[y]--;
}
if(off[x] < sum[x]/2 && off[y] < sum[y]/2){
off[x]++;
off[y]++;
dfs(cur+1);
off[x]--;
off[y]--;
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
memset(on,0,sizeof(on));
memset(off,0,sizeof(off));
memset(sum,0,sizeof(sum));
int flag = 1;
cnt = 0;
scanf("%d%d",&n,&m);
for(int i = 1; i <= m; i++){
scanf("%d%d",&a[i],&b[i]);
sum[a[i]]++;
sum[b[i]]++;
}
for(int i = 1; i <= n; i++){
if(sum[i] % 2){
flag = 0;
break;
}
}
if(flag){
dfs(1);
printf("%d\n",cnt);
}
else
printf("0\n");
}
return 0;
}
8.Cube Stacking
题目链接:
http://poj.org/problem?id=1988
解题思路:
http://blog.youkuaiyun.com/piaocoder/article/details/47959257
AC代码:
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 30005;
int pa[N];
int dis[N];
int cnt[N];
int findset(int x){
if(x == pa[x])
return pa[x];
int root = findset(pa[x]);
dis[x] += dis[pa[x]];
pa[x] = root;
return pa[x];
}
int main(){
int p;
while(~scanf("%d",&p)){
char op[5];
int a,b;
for(int i = 1; i <= N; i++){
pa[i] = i;
cnt[i] = 1;
dis[i] = 0;
}
while(p--){
scanf("%s",op);
if(op[0] == 'M'){
scanf("%d%d",&a,&b);
a = findset(a);
b = findset(b);
if(a != b){
pa[b] = a;
dis[b] = cnt[a];
cnt[a] += cnt[b];
}
}
else{
scanf("%d",&a);
b = findset(a);
printf("%d\n",cnt[b]-dis[a]-1);
}
}
}
return 0;
}
9.The Unique MST
题目链接:
http://poj.org/problem?id=1679
解题思路:
http://blog.youkuaiyun.com/piaocoder/article/details/47960579
AC代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int n,m;
struct Edge
{
int u,v,w;
int flag;
}edge[100005];
int pa[110];
int del[110];
bool cmp(Edge a,Edge b)
{
return a.w < b.w;
}
void init(){
for(int i = 1; i <= n; i++)
pa[i] = i;
}
int findset(int x)
{
if(pa[x] != x)
pa[x] = findset(pa[x]);
return pa[x];
}
int kruskal(int dell)
{
int i,u,v,cnt = n,sum = 0;
for(i = 0; i < m; i++)
{
if(i == dell)
continue;
u = findset(edge[i].u);
v = findset(edge[i].v);
if(u != v)
{
sum += edge[i].w;
pa[v] = u;
edge[i].flag = 1;
if(--cnt == 1)
break;
}
}
return sum;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
int u,v,w;
for(int i = 0; i < m; i++){
scanf("%d%d%d",&u,&v,&w);
edge[i].u = u;
edge[i].v = v;
edge[i].w = w;
edge[i].flag = 0;
}
sort(edge,edge+m,cmp);
int ans,ans1,tmp = 0,k = 0;
init();
ans = kruskal(-1);
for(int i = 1; i <= n; i++)
if(pa[i] == i)
tmp++;
if(tmp > 1){
printf("0\n");
continue;
}
for(int i = 0; i < m; i++)
if(edge[i].flag)
del[k++] = i;
int flag = 0;
for(int i = 0; i < k; i++){
init();
ans1 = kruskal(del[i]);
tmp = 0;
for(int j = 1; j <= n; j++)
if(pa[i] == i)
tmp++;
if(tmp > 1)
continue;
if(ans1 == ans){
flag = 1;
break;
}
}
if(flag)
printf("Not Unique!\n");
else
printf("%d\n",ans);
}
return 0;
}
10.Double Queue
题目链接:
http://poj.org/problem?id=3481
解题思路:
给你三种操作:
1.插入数据;
2.弹出优先级最高的数据;
3.弹出优先级最低的数据。
用set很轻松就解决了。。。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <algorithm>
using namespace std;
struct node{
int num,p;
bool operator < (const node &a) const{
return p > a.p;
}
};
set<node> s;
int main(){
s.clear();
int op,x,y;
set<node>::iterator it;
while(1){
scanf("%d",&op);
if(op == 0)
break;
else if(op == 1){
scanf("%d%d",&x,&y);
s.insert(node{x,y});
}
else if(op == 2){
if(s.size() == 0){
printf("0\n");
continue;
}
it = s.begin();
printf("%d\n",it->num);
s.erase(it);
}
else if(op == 3){
if(s.size() == 0){
printf("0\n");
continue;
}
it = s.end();
it--;
printf("%d\n",it->num);
s.erase(it);
}
}
return 0;
}