C |
待补...
D |
题意:给出一个n行m列的仅含有数字0 1的矩阵,求矩阵的秩,注意题目中有句话:每列为1的元素只有两个
分析:并查集思想,用vector存好图后,遍历每列,把1所在的点用边连起来,最后数有几条边就好
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int N,M;
vector<int>vec[maxn];
int pre[maxn];
int num[maxn];//集合内元素个数
void init2(){
for(int i=1;i<=N;++i){
int k;
cin>>k;
for(int j=1;j<=k;++j){
int ci;
cin>>ci;
vec[ci].push_back(i);//i是行,ci是列,注意不要弄混了
}
}
}
void init1(){
for(int i=0;i<=N;++i){
num[i]=1;
pre[i]=i;
}
}
int find(int x){
if(x==pre[x])
return x;
return pre[x]=find(pre[x]);
}
void join(int x,int y){
int fx=find(x);
int fy=find(y);
if(fx==fy)return;
pre[fy]=fx; //fx是fy的祖先
num[fx]+=num[fy];
}
int main()
{
ios::sync_with_stdio(false);
cin>>N>>M;
init1();
init2();
for(int i=1;i<=M;i++){//按列遍历 ,题目中说了每行只有两个数非0
int x=vec[i][0];
int y=vec[i][1];
join(x,y);
}
int ans=0;
for(int i=1;i<=N;i++) {
if(find(i)==i){
ans+=(num[i]-1);//由于num存的是点的个数,边数=点数-1
}
}
cout<<ans<<endl;
return 0;
}
F |
待补...
K |
题意:第一行给出了一个数字n,表示序列从1-n,接下来n个数表示从某个数开始的最长上升子序列个数,还原原序列
分析:思维题,只要用笔多列出几组数据就能知道,从左向右的第一个1一定是最大的,第二个1是次大的...以此类推...所以我们只需要开一个vector数组记录它们的位置即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e7+5;
const int maxn=1e5+5;
const int mod=1e9+7;
int N;
int a[maxn];
vector<int>vec[maxn];
int ans[maxn];
int main()
{
ios::sync_with_stdio(false);
cin>>N;
for(int i=1;i<=N;i++){
cin>>a[i];
vec[a[i]].push_back(i);
}
bool flag=0;
int t=N;
for(int i=1;i<=N;i++){
for(int j=0;j<vec[i].size();j++){
if(t==0){
flag=1;
break;
}
ans[vec[i][j]]=t;
t--;
}
if(flag)break;
}
for(int i=1;i<=N;i++){
cout<<ans[i]<<' ';
}
return 0;
}
G |
签到题
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e7+5;
const int maxn=1e5+5;
const int mod=1e9+7;
struct Node{
double a,t;
}p[maxn];
int N;
bool cmp(Node x,Node y){
return x.a>y.a;
}
int main()
{
ios::sync_with_stdio(false);
cin>>N;
for(int i=1;i<=N;i++){
cin>>p[i].a>>p[i].t;
}
double x1=0;
double v=0;
double v0=0;
for(int i=1;i<=N;i++){
x1+=v0*p[i].t+(0.5)*p[i].a*p[i].t*p[i].t;
v=v0+p[i].a*p[i].t;
v0=v;
}
sort(p+1,p+1+N,cmp);
double x2=0;
v=0;v0=0;
for(int i=1;i<=N;i++){
x2+=v0*p[i].t+(0.5)*p[i].a*p[i].t*p[i].t;
v=v0+p[i].a*p[i].t;
v0=v;
}
// cout<<x2<<endl;
printf("%.1f\n",abs(x1-x2));
return 0;
}
J |
题意:n堆石头,每堆ai个,两个人A,B轮流取非0数目的石头,其中B必须连续取两次,问先手能否赢
分析:emmmm,我也是看的别人的题解......先放着吧
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int N;
int one,two,x;
int main()
{
ios::sync_with_stdio(false);
cin>>N;
for(int i=1;i<=N;i++){
int ai;
cin>>ai;
if(ai==1)one++;
else if(ai==2)two++;
else x++;
}
if(N%3==0){
if(one==N-1)
cout<<"Win"<<endl;
else if(one==N-2&&two!=0)
cout<<"Win"<<endl;
else
cout<<"Lose"<<endl;
return 0;
}
if(N%3==1){
if(one==N)
cout<<"Win"<<endl;
else if(one==N-1)
cout<<"Win"<<endl;
else if(one==N-2&&two!=0)
cout<<"Win"<<endl;
else
cout<<"Lose"<<endl;
return 0;
}
if(N%3==2){
if(one==N)
cout<<"Win"<<endl;
else if(one==N-1)
cout<<"Win"<<endl;
else
cout<<"Lose"<<endl;
}
return 0;
}