还是自己菜的原因,cf一直打不好,希望借写博客来记录并提示自己吧。。
A:有n辆车(n是偶数),n/2个人,每人分配两辆车,每辆车都有一个标志值(具体代表什么,我也忘了),现在要求给每个人分配的车的价值总和都一样,输出每个人的车子号码。
题解:暴力枚举;求出所有车子的总和sum,s=2*sum / n就是 每个人分配的车子价值总和,然后对每个没有被记录的 a[i] 找到 一个同样没有标记的 s-a[i] 的元素,输出,并将这两个元素标记,即可。
#include <bits/stdc++.h>
#define nloop(a,b,c) for(LL a=b;a>=c;a--)
#define loop(a,b,c) for(LL a=b;a<=c;a++)
#define clr(a,b) memset(a,b,sizeof a)
#define x first
#define y second
#define LL long long
//#define debug
#define maxn 1000005
using namespace std;
int a[5500],book[5000];
int ser(int x,int n)
{
loop(i,1,n)
if(a[i]==x&&book[i]>0)
return i;
}
int main()
{
//freopen("data.txt","r",stdin);
int n,s=0,p,d;
scanf("%d",&n);
loop(i,1,n)
scanf("%d",&a[i]),s+=a[i],book[i]=1;
p=n/2;
d=s/p;
//cout<<d<<endl;
loop(i,1,n)
{
if(book[i]>0)
{
//cout<<book[d-a[i]]<<endl;
book[i]--;
int pos=ser(d-a[i],n);
book[pos]--;
cout<<i<<" "<<pos<<endl;
}
}
}
B:有个棋盘n*n那么大,有m个皇后,每次放一个皇后进去,然后统计当前还有多少个空格是可以走的
题解:n很大,不可能暴力去枚举或者开个二维数组去标记,我们用row[i]表示第i行是否能走,col[i]表示第i列是否能走,add1表示行被标记的个数,add2表示列被标记的个数,如果把x,y放到棋盘,初始ans=n*n,分了三种情况
1:x行,y列都没有被标记过 ,那么ans -=n-add1+n-add2-1,add1++,add2++;
2:x行标记过,y列没被标记,那么ans -=n-add1,add2++;
3:x行没被标记过,y列被标记过,那么ans-=n-add2,add1++;
#include <bits/stdc++.h>
#define nloop(a,b,c) for(LL a=b;a>=c;a--)
#define loop(a,b,c) for(LL a=b;a<=c;a++)
#define clr(a,b) memset(a,b,sizeof a)
#define x first
#define y second
#define LL long long
//#define debug
#define maxn 1000005
using namespace std;
int row[maxn],col[maxn];
int main()
{
//freopen("data.txt","r",stdin);
LL n,m,x,y,ans;
scanf("%I64d %I64d",&n,&m);
ans=n*n;
LL add1=0,add2=0;
loop(i,1,m)
{
scanf("%I64d %I64d",&x,&y);
if(!row[x]&&!col[y])
{
ans-=2*(n-1)-add1-add2-1;
add1++;
add2++;
}
else if(!row[x])
{
ans-=n-add1;
add2++;
}
else if(!col[y])
{
ans-=n-add2;
add1++;
}
cout<<ans<<" "<<endl;
row[x]=col[y]=1;
}
}
C:对于一个字符串,每个字符串都是大写或小写字母,求最短的长度,完全包含该字符串里所有字符
题解:经典尺取法。先O(n)求出总共有多少种字符num。把字符一个一个加到队列,统计队列里面的字符种数,不够num,继续加入,如果够了,更新ans=min(ans,Q.size()),将第一个字符出队,重复上述操作。
#include <bits/stdc++.h>
#define nloop(a,b,c) for(LL a=b;a>=c;a--)
#define loop(a,b,c) for(LL a=b;a<=c;a++)
#define clr(a,b) memset(a,b,sizeof a)
#define x first
#define y second
#define LL long long
#define maxn 100005
using namespace std;
int flag[300];
int main()
{
//freopen("data.txt","r",stdin);
int num=0,n;
queue<char> Q;
string ch;
cin>>n>>ch;
loop(i,0,ch.size()-1)
{
if(!flag[ch[i]])
num++,flag[ch[i]]=1;
}
clr(flag,0);
int t=0,ans=n+1,l,r;
loop(i,0,ch.size()-1)
{
if(t<num)
{
Q.push(ch[i]);
if(!flag[ch[i]]) t++;
flag[ch[i]]++;
}
if(t==num)
{
while(!Q.empty()&&flag[Q.front()]>1)
flag[Q.front()]--,Q.pop();
ans=min(ans,(int)Q.size());
flag[Q.front()]--;
Q.pop();
t--;
}
}
cout<<ans<<endl;
}
D:有n个学生,一辆车,目的地距离为L ,学生速度为v1,车速度为v2,求最短的时间使得所有的学生都到达目的地。
题解:如果时间最小 那么最后一定是每个人都同时到达终点
可以假定 所有人 走路时间都为t1 搭车时间都为t2,那么车子每次回头去载人的时间就是t3=t2*(v2-v1)/(v2+v1)
可以列出
(num-1)*( t2 + t3 )*v1+t2*v2=L
t2*v2+t1*v1=L
解出t1 t2 相加就是答案了
#include <bits/stdc++.h>
#define nloop(a,b,c) for(LL a=b;a>=c;a--)
#define loop(a,b,c) for(LL a=b;a<=c;a++)
#define clr(a,b) memset(a,b,sizeof a)
#define x first
#define y second
#define LL long long
#define maxn 100005
using namespace std;
int flag[300];
int main()
{
//freopen("data.txt","r",stdin);
int num=0,n,k;
double l,v1,v2;
cin>>n>>l>>v1>>v2>>k;
double t,t1,t2;
num=n/k+((n%k)?1:0);
t2=1.0*l/(v2+1.0*v1*(num-1)*(2*v2/(v1+v2)));
t=t2+(2*v2/(v1+v2))*(num-1)*t2;
printf("%.10lf\n",t);
}