这场比赛感觉。。。怎么说呢,WA、TLE、RE、MLE、PE、CE都有,做题十分钟,改BUG一小时(心情复杂)。
A - Replace To Make Regular Bracket Sequence CodeForces - 612C
题意:给你()、[]、{}、<>四种括号,任意左括号之间或者右括号之间都可以变换。现在给你一个括号组成的字符串,问使其中括号之间完全配对最少需要变换几次,若无法完全配对则输出-1。
题解:模拟,因为里层的括号一定优先配对,所以最少变换次数也就是从最里层开始配,按部就班来就好。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
stack<char>s;
int main()
{
string x;
while(cin>>x)
{
while(!s.empty()) s.pop();
int n=x.length();
int ans=0;
for(int i=0;i<n;i++)
{
if(s.empty()) s.push(x[i]);
else
{
if(x[i]==')'&&s.top()=='(')
{
s.pop();
}
else if(x[i]==']'&&s.top()=='[')
{
s.pop();
}
else if(x[i]=='}'&&s.top()=='{')
{
s.pop();
}
else if(x[i]=='>'&&s.top()=='<')
{
s.pop();
}
else if((x[i]==')'||x[i]==']'||x[i]=='}'||x[i]=='>')&&(s.top()=='('||s.top()=='{'||s.top()=='['||s.top()=='<'))
{
ans++;
s.pop();
}
else
{
s.push(x[i]);
}
}
}
if(s.empty())
printf("%d\n",ans);
else
printf("Impossible\n");
}
}
B - Pearls in a Row CodeForces - 620C
题意:给你一个序列,其中包含两个相同数字的子序列被称为好序列,问最多可以划分成几个好序列。
题解:模拟,这里两个相同的数字不一定是好序列的头和尾,因为所有好序列必须可以拼成最初的整个序列。这里我用map记录前面是否有相同数字,再用个数组存下好序列的尾,最后直接输出。
#include<iostream>
#include<cstdio>
#include<map>
using namespace std;
int a[1000000+10];
int ans[1000000+10];
map<int,bool>q;
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
q.clear();
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
int m=0;
for(int i=1;i<=n;i++)
{
if(q[a[i]])
{
m++;
ans[m]=i;
q.clear();
}
else
{
q[a[i]]=1;
}
}
if(!m)
{
printf("-1\n");
}
else
{
printf("%d\n",m);
int last=1;
for(int i=1;i<=m;i++)
{
if(i==m)
{
printf("%d %d\n",last,n);//边界是最后一个数字
}
else
{
printf("%d %d\n",last,ans[i]);
last=ans[i]+1;
}
}
}
}
return 0;
}
C - 排列2 HDU - 1716
题意:现有四张卡片,用这四张卡片能排列出很多不同的4位数,要求按从小到大的顺序输出这些4位数。
题解:四位数首先前面不能有0,其次卡片可能有重复所以要去重,这里我用的dfs+set去重
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
char a[100];
char b[100];
bool vis[100];
set<string>s;
set<string>::iterator it;
void dfs(int x)
{
if(x>4)
{
string now="";
for(int i=1;i<=4;i++)
{
now+=b[i];
}
s.insert(now);
return;
}
for(int i=1;i<=4;i++)
{
if(!vis[i])
{
vis[i]=1;
b[x]=a[i];
dfs(x+1);
vis[i]=0;
}
}
}
int main()
{
int t=0;
while(cin>>a[1]>>a[2]>>a[3]>>a[4])
{
s.clear();
if(a[1]=='0'&&a[2]=='0'&&a[3]=='0'&&a[4]=='0') break;
t++;
if(t!=1)
{
printf("\n");
}
sort(a+1,a+4+1);
dfs(1);
string now="0000";
string last="0000";
bool flag=0;
for(it=s.begin();it!=s.end();it++)
{
now=*it;
if(now[0]!='0')
{
if(now[0]!=last[0])
{
if(!flag)
{
flag=1;
}
else
{
cout<<endl;
}
}
else
{
cout<<" ";
}
cout<<now;
}
last=now;
}
printf("\n");
}
return 0;
}
D - Can you find it? HDU - 2141
题意:给你三个数字L、M、N接下来三行分别有L个、M个和N个数字,以下S组询问,问能否从三组数字中各选一个数字使和等于X,输出YES或者NO。
题解:二分,先将前两组数字两两相加,再在第三组数字中寻找能凑出X的数,每次询问复杂度L * M * logn。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[505],b[505],c[505];
int es[250000+10];
int main()
{
int n,m,l;
int t=0;
while(scanf("%d%d%d",&n,&m,&l)!=EOF)
{
t++;
printf("Case %d:\n",t);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++) scanf("%d",&b[i]);
for(int i=1;i<=l;i++) scanf("%d",&c[i]);
int r=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
r++;
es[r]=a[i]+b[j];
}
}
sort(es+1,es+r+1);
int k;
scanf("%d",&k);
for(int i=1;i<=k;i++)
{
int x;
scanf("%d",&x);
bool flag=0;
for(int j=1;j<=l;j++)
{
if(*lower_bound(es+1,es+r+1,x-c[j])==x-c[j])
{
flag=1;
break;
}
}
if(flag)
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
}
}
E - Legal or Not [HDU - 3342]
题意:n个人,m组关系。A B表示A是B的上级,而且关系之间是相互传递的,比如A是B的上级,B是C的上级,那么A也是C的上级。但是如果A是B的上级,B是C的上级,而C又是A的上级,那么关系就矛盾了。现在问你关系是否矛盾。
题解:bfs找是否存在一个圈。
F - Ignatius and the Princess IV HDU - 1029
题意:给你N个数字,让你找出哪个数字出现在(n+1)/2次(该数字一定存在且唯一)。
题解:模拟,排序后直接找。
G - Can you solve this equation? HDU - 2199
给你一个数字Y,让你求8x^4 + 7x^3 + 2x^2 + 3x + 6 == Y的解,答案在0到100直接,没有则输出-1.。
题解:二分答案,注意精度问题。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
double check(double mid)
{
return 8*mid*mid*mid*mid+7*mid*mid*mid+2*mid*mid+3*mid+6;
}
double del(double y)
{
double l=0,r=100;
while(r-l>1e-7)
{
double mid=(l+r)/2;
if(check(mid)<=y)
{
l=mid;
}
else
{
r=mid;
}
}
return r;
}
int main()
{
int t;
scanf("%d",&t);
double y;
while(t--)
{
scanf("%lf",&y);
if(y<check(0)||y>check(100))
{
printf("No solution!\n");
}
else
{
printf("%.4lf\n",del(y));
}
}
return 0;
}
H - Ordering Tasks UVA - 10305
题意:有一些任务,其中A B表示A任务排在B任务前面,求可能存在的任务顺序。
题解:拓扑排序
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
const int maxn=10000+10;
stack<int>s;
struct cc{
int from,to;
}es[maxn];
int first[maxn],nxt[maxn];
bool vis[maxn];
bool pd[105][105];
int tot=0;
void build(int ff,int tt)
{
es[++tot]=(cc){ff,tt};
nxt[tot]=first[ff];
first[ff]=tot;
}
int ru[maxn];
int ans[maxn];
int m;
int n,k;
void del()
{
for(int i=1;i<=n;i++)
{
if(ru[i]==0&&!vis[i])
{
//puts("233");
m++;
ans[m]=i;
s.push(i);
vis[i]=1;
}
}
while(!s.empty())
{
int u=s.top(); s.pop();
for(int i=first[u];i;i=nxt[i])
{
int v=es[i].to;
ru[v]--;
}
}
if(m!=n)
{
del();
}
}
int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
if(n==0&&k==0) break;
tot=0;
m=0;
memset(nxt,0,sizeof(nxt));
memset(vis,0,sizeof(vis));
memset(pd,0,sizeof(pd));
memset(first,0,sizeof(first));
int x,y;
for(int i=1;i<=k;i++)
{
scanf("%d%d",&x,&y);
if(!pd[x][y])
{
ru[y]++;
build(x,y);
}
}
del();
for(int i=1;i<n;i++)
{
cout<<ans[i]<<" ";
}
cout<<ans[n]<<endl;
}
return 0;
}
I - I Can Guess the Data Structure! UVA - 11995
题意:给你一些操作 1 X表示插入X元素,2 Y表示弹出元素Y,问你能完成这些操作的数据结构是queue、stack、priority_queue的哪一种,如果满足一个以上输出not sure,一个都不满足输出impossible。
题解:直接用三个数据结构模拟,有可能出现数据结构为空依然弹出的操作,注意防止RE。
#include<iostream>
#include<cstdio>
#include<queue>
#include<stack>
using namespace std;
queue<int>q1;
priority_queue<int>q2;
stack<int>q3;
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
while(!q1.empty()) q1.pop();
while(!q2.empty()) q2.pop();
while(!q3.empty()) q3.pop();
int flag1=1,flag2=1,flag3=1;
for(int i=1;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
if(x==1)
{
q1.push(y);
q2.push(y);
q3.push(y);
}
else
{
if(q1.empty()||q1.front()!=y) flag1=0;
if(q2.empty()||q2.top()!=y) flag2=0;
if(q3.empty()||q3.top()!=y) flag3=0;
if(!q1.empty()) q1.pop();
if(!q2.empty()) q2.pop();
if(!q3.empty()) q3.pop();
}
}
if(flag1+flag2+flag3==1)
{
if(flag1==1)
{
printf("queue\n");
}
if(flag2==1)
{
printf("priority queue\n");
}
if(flag3==1)
{
printf("stack\n");
}
}
if(flag1+flag2+flag3>1)
{
printf("not sure\n");
}
if(flag1+flag2+flag3<1)
{
printf("impossible\n");
}
}
}
J - 4 Values whose Sum is 0 UVA - 1152
题意:n行,每行四个数字,从四列中个取一个数字,使其和为零,问可以找出几组这样的数字。
题解:二分,前两列一组,后两列一组,两两相加,二分查找和为零。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
long long a[4005][5];
long long b[16000000+10];
int n;
int check(long long x)
{
int l=1,r=n*n;
while(l<=r)
{
int mid=(l+r)/2;
if(b[mid]<x)
{
l=mid+1;
}
else if(b[mid]>x)
{
r=mid-1;
}
else if(b[mid]==x)
{
//cout<<b[mid]<<endl;
int sum=1;
for(int i=mid+1;i<=n*n;i++)
{
if(b[i]==x)
{
sum++;
}
else
{
break;
}
}
for(int i=mid-1;i>=1;i--)
{
if(b[i]==x)
{
sum++;
}
else
{
break;
}
}
return sum;
}
}
return 0;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld%lld%lld",&a[i][1],&a[i][2],&a[i][3],&a[i][4]);
}
int m=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
m++;
b[m]=a[i][1]+a[j][2];
}
}
sort(b+1,b+m+1);
int ans=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
long long now=a[i][3]+a[j][4];
ans+=check(-now);
}
}
printf("%d\n",ans);
if(t!=0)
{
printf("\n");
}
}
return 0;
}