19香港补题(G)+cf思维
Posted 钟钟终
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了19香港补题(G)+cf思维相关的知识,希望对你有一定的参考价值。
算法方面,最近自己是有些进步;
但仍然有很多训练时间浪费掉的,有些疲倦,但真的不想退役后才后悔当初要是怎么样就会怎么样。
我们距离区域赛的稳铜还是有些差距的,继续努力吧。
专业学习方面,找对方法,静下心来去学。虽然说大部分时间都要留给队友一起训练,但是总会有早起、零散的时间可以利用,提高效率,好吧!
不要跟个废物一样,懒惰、抱怨、怕麻烦、说废话、迟疑不决、得过且过。最后不到一年,坚持下去,我相信自己可以实现很多事情,前提是先让自己配得上。我想要的东西很贵,想见的人很远。
G. Game Design
题意:构造一棵树,每个叶子节点都会有怪兽,可选择若干点上建造攻击塔,每个攻击塔的建造价值不同。要求构造的方式有k种,且每种方式的总价值相同,输出构造的树和每个点的权值大小。
思路:
1.思考了很久。设f(x)表示以x为根节点所贡献的构造方法数 ,
得出公式:f(x)=f(v1) * f(v2) *...*f(v3)+1
2.若是从二叉树的角度思考,便只需根据k分化后的奇偶性进行递归即可。
k为奇数:2*f(k/2)+1
k为偶数:1+f(k-1)
此时k-1为奇数。
注意点:若val==1时,剩下k个点构造成一条链;若k ==2时,此时u所连两个子节点为val/2
#include <bits/stdc++.h>
#define int long long
#define ios cin.tie(0),cout.tie(0),ios::sync_with_stdio(0);
#define endl '\\n'
#define ULL unsigned long long
#define down 0.996
using namespace std;
const int N=3e5+5;
const int inf=1e18;
int f[N],ans[N],cnt;
void dfs(int x,int val,int k)
ans[x]=val;
if(k==1) return;
if(val==1)
for(int i=1;i<k;i++)
f[++cnt]=cnt-1,ans[cnt]=1;
return;
if(k%2)
f[++cnt]=x;dfs(cnt,val/2,2);
f[++cnt]=x;dfs(cnt,val/2,k/2);
else
if(k==2)
f[++cnt]=x;dfs(cnt,val/2,1);
f[++cnt]=x;dfs(cnt,val/2,1);
else
f[++cnt]=x;dfs(cnt,val/2,1);
f[++cnt]=x;dfs(cnt,val/2,k-1);
void solve()
//cout<<(1<<29)<<endl; 536870912
int k;cin>>k;
if(k==1)
cout<<2<<endl<<1<<endl<<1<<" "<<2<<endl;return;
else if(k==2)
cout<<2<<endl<<1<<endl<<1<<" "<<1<<endl;return;
else
cnt=1;
dfs(1,1<<29,k);
cout<<cnt<<endl;
for(int i=2;i<=cnt;i++) cout<<f[i]<<" ";cout<<endl;
for(int i=1;i<=cnt;i++) cout<<ans[i]<<" ";cout<<endl;
signed main()
//ios;
//int T;cin>>T;
//while(T--)
solve();
return 0;
G. Orray
直接从排序规则入手。
#include <bits/stdc++.h>
#define int long long
#define ios cin.tie(0),cout.tie(0),ios::sync_with_stdio(0);
#define endl '\\n'
#define ULL unsigned long long
#define down 0.996
using namespace std;
const int N=3e5+5;
const int inf=1e18;
int n,a[N],ans;
bool cmp1(int a,int b)return a>b;
bool cmp2(int a,int b)return (a|ans)>(b|ans);
void solve()
cin>>n;
ans=0;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1,cmp1);
int num=min(n,30LL);
for(int i=1;i<=num;i++)
sort(a+i,a+n+1,cmp2);
ans|=a[i];
for(int i=1;i<=n;i++) cout<<a[i]<<" ";
cout<<endl;
signed main()
ios;
int T;cin>>T;
while(T--)
solve();
return 0;
从二进制位入手:
#include <bits/stdc++.h>
#define int long long
#define ios cin.tie(0),cout.tie(0),ios::sync_with_stdio(0);
#define endl '\\n'
#define ULL unsigned long long
#define down 0.996
using namespace std;
const int N=3e5+5;
const int inf=1e18;
int n,a[N],p[N],cnt;
bool vis[N];
vector<int>e[35];
map<int,int>mp;
void solve()
mp.clear();
cin>>n;
for(int i=0;i<=n;i++) a[i]=p[i]=vis[i]=0;
for(int i=0;i<=30;i++) e[i].clear();
cnt=0;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int j=30;j>=0;j--)
if((a[i]>>j)&1==1) e[j].push_back(i);
int g=0,id=0;
for(int i=30;i>=0;i--)
if(e[i].size()>0&&!mp[i])
int tmp=g|a[e[i][0]],id=e[i][0];
//cout<<i<<" "<<tmp<<" "<<e[i][0]<<" "<<id<<endl;
for(int j=1;j<e[i].size();j++)
if((g|a[e[i][j]])>tmp)
tmp=g|a[e[i][j]],id=e[i][j];
g=tmp,p[++cnt]=id;
//cout<<g<<endl;
for(int j=30;j>=0;j--)
if((g>>j)&1==1) mp[j]=1;
// for(int i=1;i<=cnt;i++)
// cout<<p[i]<<" -- ";cout<<endl;
for(int i=1;i<=cnt;i++)
if(!vis[p[i]])
vis[p[i]]=1;
cout<<a[p[i]]<<" ";
for(int i=1;i<=n;i++)
if(!vis[i]) cout<<a[i]<<" ";
cout<<endl;
signed main()
ios;
int T;cin>>T;
while(T--)
solve();
return 0;
F. Smaller
读错题了,按照自己理解的题意做了另一个题。。。起码一题当两题做了;
原题思路:我只要保证a最小,b最大,若是a和b都只包含字符a,那我们去比较他们长度。
#include <bits/stdc++.h>
#define int long long
#define ios cin.tie(0),cout.tie(0),ios::sync_with_stdio(0);
#define endl '\\n'
#define ULL unsigned long long
#define down 0.996
using namespace std;
const double eps=1e-8;
const double inf=1e18;
const int mod=998244353;
const int P=131;
const int N=3e3+5;
int q,d,k;
string s;
void solve()
cin>>q;
int f1=0,f2=0,s1=1,s2=1;
while(q--)
cin>>d>>k>>s;
if(d==1) s1+=k*s.length();
else s2+=k*s.length();
for(int i=0;s[i];i++)
if(s[i]!='a'&&d==1) f2=1;
else if(s[i]!='a'&&d==2) f1=1;
if(f1) cout<<"YES"<<endl;
else if(f2) cout<<"NO"<<endl;
else
if(s1>=s2) cout<<"NO"<<endl;
else
cout<<"YES"<<endl;
signed main()
ios;
int T;cin>>T;
while(T--)
solve();
return 0;
假题思路:错以为s和t都要按照字典序最小排列,然后比较。
#include <bits/stdc++.h>
#define int long long
#define ios cin.tie(0),cout.tie(0),ios::sync_with_stdio(0);
#define endl '\\n'
#define ULL unsigned long long
#define down 0.996
using namespace std;
const double eps=1e-8;
const double inf=1e18;
const int mod=998244353;
const int P=131;
const int N=3e3+5;
int q,d,k;
string s;
unordered_map<char,int>m1,m2;
void solve()
m1.clear();m2.clear();
m1['a']=m2['a']=1;
cin>>q;
while(q--)
cin>>d>>k>>s;
int f1=0,f2=0,f3=0;
if(d==1)
for(int i=0;i<s.length();i++)
m1[s[i]]+=k;
else
for(int i=0;i<s.length();i++)
m2[s[i]]+=k;
for(int i=25;i>=0;i--)
if(m1[char('a'+i)])
f1=i;break;
for(int i=25;i>=0;i--)
if(m2[char('a'+i)])
f2=i;break;
cf 595 补题