E
poj1456
emmm,一开始用的暴力,过了。。。(数据好水,我甚至cmp忘记写在价值相同时,需要返回更大的时间了)
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
typedef pair<int,int> P;
P a[10010];
int cmp(P a, P b)
{
return a.first>b.first;
}
bool use[10010];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
while(cin>>n)
{
for(int i=0;i<n;i++)
{
cin>>a[i].first>>a[i].second;
}
sort(a,a+n,cmp);
fill(use,use+10005,true);
int asd=0;
for(int i=0;i<n;i++)
{
while(!use[a[i].second] && a[i].second>0)
a[i].second--;
if(use[a[i].second] && a[i].second>0)
{
use[a[i].second]=false;
asd+=a[i].first;
}
}
cout<<asd<<"\n";
}
return 0;
}
然后看了看题解,淦,居然可以拿并查集优化的
学习了下 每次更新的时候,假如这个点从未使用过的话,从-1更新为qwe-1,例如样例1的4 50 2 10 1 20 2 30 1
先是50 2,那么讲par[2]更新为1,代表1已经使用过了,再是30 1,将par[1]更新为0,那么下次查询20 2的时候,会把par[2]也更新为par[1]的值0,省去了贪心重复找的时间
重点:初始化的时候记得全部初始为-1,直接开到10000
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define maxn 10010
int par[maxn];//父亲
int knar[maxn];//树的高度
int find(int x)//查询树的根
{
if(par[x]==-1)
{
return x;
}
else
return par[x]=find(par[x]);
}
void init(int n)//初始化n个元素
{
for(int i=0;i<=n;i++)
{
par[i]=-1;
knar[i]=0;
}
}
void unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y)
return ;
if(knar[x]<knar[y])
{
par[x]=y;
}
else
par[y]=x;
if(knar[x]==knar[y])
knar[x]++;
}
bool same(int x,int y)
{
return find(x)==find(y);
}
typedef pair<int,int> P;
P a[10010];
int cmp(P a, P b)
{
return a.first>b.first;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
while(cin>>n)
{
for(int i=1;i<=n;i++)
{
cin>>a[i].first>>a[i].second;
}
sort(a+1,a+n+1,cmp);
init(10005);
int asd=0;
for(int i=1;i<=n;i++)
{
// cout<<find(a[i].second)<<'\n';
int qwe=find(a[i].second);
// if(find(a[i].second)>0)
if(qwe>0)
{
par[qwe]=qwe-1;
asd+=a[i].first;
}
}
cout<<asd<<"\n";
}
return 0;
}
F
其实感觉直接用连通图的性质就能做,但既然是并查集专项训练就用并查集呗
这题卡了我实际上1个小时。。。自做聪明的认为1必然是起点了,不用统计1号点的数据,直接输出就好,但其实因为输入顺序的不同1号点的祖先节点有可能不是1自己,比如先输入1 2时,par[1]=1,par[2]=2,而先输入2,1时,par[2]=1,par[1]=2。。。。
导致疯狂wa
ac代码
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define maxn 1010
int par[maxn];//父亲
int knar[maxn];//树的高度
int find(int x)//查询树的根
{
if(par[x]==x)
{
return x;
}
else
return par[x]=find(par[x]);
}
void init(int n)//初始化n个元素
{
for(int i=1;i<=n;i++)
{
par[i]=i;
knar[i]=0;
}
}
void unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y)
return ;
if(knar[x]<knar[y])
{
par[x]=y;
}
else
par[y]=x;
if(knar[x]==knar[y])
knar[x]++;
}
bool same(int x,int y)
{
return find(x)==find(y);
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
int n,m,a,b;
while(cin>>n)
{
if(n==0)
return 0;
cin>>m;
init(n+5);
while(m--)
{
cin>>a>>b;
unite(a,b);
}
int asd=0;
for(int i=1;i<=n;i++)
{
if(find(i)==i)
asd++;
}
cout<<asd-1<<"\n";
}
return 0;
}
那我又想了,这是因为1的祖先节点有可能被更新为其他的,那我在更新节点时,假如一个数字和1进行合并时,强制他更改为1,而不考虑树的秩呢?那我最后统计的时候是不是就可以直接从2开始统计,不用管1了呢,试了下,是可以的,但不建议你们这么试,因为为了少一次统计。。。导致其他操作变多了,很亏,我主要是不服气。。。
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
#define maxn 1010
int par[maxn];//父亲
int knar[maxn];//树的高度
int find(int x)//查询树的根
{
if(par[x]==x)
{
return x;
}
else
return par[x]=find(par[x]);
}
void init(int n)//初始化n个元素
{
for(int i=1;i<=n;i++)
{
par[i]=i;
knar[i]=0;
}
}
void unite(int x,int y)
{
if(x==1)
{
par[find(y)]=find(x);
return ;
}
x=find(x);
y=find(y);
if(x==y)
return ;
if(x==1)
{
par[y]=x;
return ;
}
if(y==1)
{
par[x]=y;
return ;
}
if(knar[x]<knar[y])
{
par[x]=y;
}
else
par[y]=x;
if(knar[x]==knar[y])
k nar[x]++;
}
bool same(int x,int y)
{
return find(x)==find(y);
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
int n,m,a,b;
while(cin>>n)
{
if(n==0)
return 0;
cin>>m;
init(n+5);
while(m--)
{
cin>>a>>b;
unite(min(a,b),max(a,b));
}
int asd=0;
for(int i=2;i<=n;i++)
{
if(find(i)==i)
asd++;
}
cout<<asd<<"\n";
}
return 0;
}
G
认真读题认真读题认真读题
没啥好讲的,我一开始以为2个子序列不需要连续,后来发现是连续的,那很简单了,stl大法好
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
string s1,s2,s3;
cin>>s1>>s2>>s3;
long long n=0,m=0;
int qwe=0,asd=0;
n=s1.find(s2,0);
m=s1.find(s3,n+s2.size());
if(n!=string::npos && m!=string::npos)
qwe=1;
reverse(s1.begin(),s1.end());
n=s1.find(s2,0);
m=s1.find(s3,n+s2.size());
if(n!=string::npos && m!=string::npos)
asd=1;
if(qwe && asd)
cout<<"both\n";
else
if(qwe==0 && asd==1)
cout<<"backward\n";
else
if(asd==0 && qwe==1)
cout<<"forward\n";
else
cout<<"fantasy\n";
return 0;
}
H题
傻逼题
#include <bits/stdc++.h>
using namespace std;
int main()
{
int a,b;
cin>>a>>b;
a=max(a,b);
switch(a)
{
case 1:{
cout<<"1/1\n";
break;
}
case 2:{
cout<<"5/6\n";
break;
}
case 3:{
cout<<"2/3\n";
break;
}
case 4:{
cout<<"1/2\n";
break;
}
case 5:{
cout<<"1/3\n";
break;
}
case 6:{
cout<<"1/6\n";
break;
}
}
return 0;
}
I题
更傻逼了
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,a,b,c,q,w,y,x;
int p1,p2,p3;
cin>>n>>p1>>p2>>p3>>q>>w;
int s=0;
int ans=0;
for(int i=1;i<=n;i++)
{
cin>>x>>y;
ans+=(y-x)*p1;
if(s!=0)
{
if(x-s>w+q)
{
ans+=(x-s-w-q)*p3;
ans+=w*p2;
ans+=q*p1;
}
else
if(x-s>q)
{
ans+=(x-s-q)*p2;
ans+=q*p1;
}
else
{
ans+=(x-s)*p1;
}
}
s=y;
}
cout<<ans<<"\n";
return 0;
}
L题
我是傻逼
#include <bits/stdc++.h>
using namespace std;
int a[10];
int main()
{
cin>>a[0];
cin>>a[1];
cin>>a[2];
cin>>a[3];
sort(a,a+4);
int qwe=1;
if(a[0]+a[1]>a[2])
{
cout<<"TRIANGLE\n";
}
else
if(a[1]+a[2]>a[3])
cout<<"TRIANGLE\n";
else
if(a[0]+a[1]==a[2] || a[1]+a[2]==a[3])
{
cout<<"SEGMENT\n";
}
else
cout<<"IMPOSSIBLE\n";
return 0;
}