1,Fedor and New Game;2,谜一样的牛+pbds初学+vector模拟平衡树;3,剪枝;
1,Fedor and New Game
lowbit 操作取最低位1;
找各个位置上的数,相同位置,数字不同的最多限制个数为k个;
#include<bits/stdc++.h>
#define rep1(i,a,n) for(register ll i=a;i<n;i++)
#define rep2(i,a,n) for(register ll i=a;i<=n;i++)
#define per1(i,n,a) for(register ll i=n;i>a;i--)
#define per2(i,n,a) for(register ll i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define INF 0x3f3f3f3f
#define pb push_back
#define endl "\n"
#define xiaoshu(a) setprecision(a)
#define lowbit(x) (-x&x)
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
const int N=1e4+10;
int n,m,k;
int x[N];
bool isfriend(int x,int y)
{
int cs=0;
while(x!=0||y!=0)
{
if(x%2!=y%2)cs++;
x>>=1;
y>>=1;
if(cs>k)return 0;
}
return 1;
}
signed main()
{
quick_cin();
cin>>n>>m>>k;
rep2(i,1,m)cin>>x[i];
int x1;cin>>x1;
int ans=0;
rep2(i,1,m)
{
if(isfriend(x[i],x1))
{
ans++;
}
}
cout<<ans;
return 0;
}
2,谜一样的牛;
题意:
一共1~n个身高的n头牛,n头牛站成一排,给出n-1行数,表示第i头的前边有多少头比他高的牛;
解法:从后往前找,该头牛的身高,为队伍里剩下的牛的第rank+1头牛 ;
rank:0,从1 2 3 4 5中,第0+1小的牛,即身高为1的牛;
rank:1,从2 3 4 5中,第1+1头小的牛,即身高为3的牛;
。。。
最终能找完;
两步操作:1,从队伍里找到第k小的数;2,从队伍里删除一个数;
所以平衡树很容易解决,虽然有点杀鸡焉用牛刀的感觉,但是vector写刚好快些;
第一时间想到了vector来做,正好熟悉下vector 的操作;
a.reserve(N)给a向量预先分配容量为N;vector容量和size是两码事!
扩容量是个耗费时间的过程,所以不如预先设置好容量!;
- 插入数值 xx。
- 删除数值 xx(若有多个相同的数,应只删除一个)。
- 查询数值 xx 的排名(若有多个相同的数,应输出最小的排名)。
- 查询排名为 xx 的数值。
- 求数值 xx 的前驱(前驱定义为小于 xx 的最大的数)。
- 求数值 xx 的后继(后继定义为大于 xx 的最小的数)。
case 1:a.insert(upper_bound(a.begin(),a.end(),x),x); break;
case 2:a.erase(lower_bound(a.begin(),a.end(),x)); break;
case 3:cout<<lower_bound(a.begin(),a.end(),x)-a.begin()+1<<endl; break;
case 4:cout<<a[x-1]<<endl; break;
case 5:cout<<(*--lower_bound(a.begin(),a.end(),x))<<endl; break;
case 6:cout<<(*upper_bound(a.begin(),a.end(),x))<<endl; break;
#include<bits/stdc++.h>
#define rep1(i,a,n) for(register ll i=a;i<n;i++)
#define rep2(i,a,n) for(register ll i=a;i<=n;i++)
#define per1(i,n,a) for(register ll i=n;i>a;i--)
#define per2(i,n,a) for(register ll i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define INF 0x3f3f3f3f
#define pb push_back
#define endl "\n"
#define xiaoshu(a) setprecision(a)
#define lowbit(x) (-x&x)
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
const int N=1e6+10;
vector<int>niu;
vector<int>ans;
signed main()
{
quick_cin();
cin>>n;
niu.reserve(N);
ans.reserve(N);
niu.pb(1);
rep2(i,2,n)
{
cin>>b[i];
niu.pb(i);
}
per2(i,n,1)
{
if(i>1)
{
ans.pb(niu[b[i]]);
niu.erase(lower_bound(niu.begin(),niu.end(),niu[b[i]]));
}
else ans.pb(niu[0]);
}
per2(i,ans.size()-1,0)cout<<ans[i]<<endl;
return 0;
}
pbds库的平衡树:
dev不能用#include<bits/extc++.h>;
需要把用到的打出来,也就4种东西,平衡树,哈希表,trie树和优先队列;
也是从0开始的,所以输出第x个数就是*tr.find_by_order(x-1);
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#include<ext/pb_ds/trie_policy.hpp>
#include<ext/pb_ds/priority_queue.hpp>
#define rep1(i,a,n) for(register ll i=a;i<n;i++)
#define rep2(i,a,n) for(register ll i=a;i<=n;i++)
#define per1(i,n,a) for(register ll i=n;i>a;i--)
#define per2(i,n,a) for(register ll i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define endl "\n"
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
int n;
using treap=tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;
treap tr;
const int N=1e5+10;
int pm[N];
int as[N],k;
signed main()
{
quick_cin();
cin>>n;
tr.insert(1);
rep2(i,2,n)tr.insert(i),cin>>pm[i];
per2(i,n,1)
{
if(i!=1)
{
int ans=*tr.find_by_order(pm[i]);
as[k++]=ans;
tr.erase(tr.lower_bound(ans));
}
else
{
as[k++]=*tr.find_by_order(0);
}
}
per2(i,k-1,0)cout<<as[i]<<endl;
return 0;
}
竟然和用vector模拟的平衡树时间差不多,。。,也没快多少貌似。。 ;还是手写的牛啊;
还有就是谜一样的牛
使用复杂的pbds操作,没想到和vecto模拟的平衡树不相上下,甚至有时还慢,被坑了感觉。。而且pbds的树无法插入相同元素,反而vector可以;
所以要不要用pbds?平衡树已经可以用上面的vector来模拟了,并且写法更简洁,需要的头文件和相关操作也少,所以还是作为了解吧!
3,剪枝;
泉水:
题意:一共n个桶(n为偶数),对应n/2个挑水时间,每次可以取i,j两个桶,消耗t[i][j]时间,
打满所有的桶所需的最短时间;
主要是枚举状态,因为本质上还是在1~n种选,只不过一次要拿两个,所以枚举的状态有些变化;
另外就是剪枝了;
#include<bits/stdc++.h>
//#include<ext/pb_ds/assoc_container.hpp>
#define rep1(i,a,n) for(register ll i=a;i<n;i++)
#define rep2(i,a,n) for(register ll i=a;i<=n;i++)
#define per1(i,n,a) for(register ll i=n;i>a;i--)
#define per2(i,n,a) for(register ll i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define endl "\n"
#define lowbit(x) (-x&x)
using namespace std;
//using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
int t[100][100];
bool hs[100];
int n;
int ans=INT_MAX;
void dfs(int x,int sum)
{
if(x>n)
{
ans=min(ans,sum);
return;
}
if(sum>=ans)return;
if(!hs[x])
{
hs[x]=1;
rep2(i,1,n)
{
if(!hs[i])
{
hs[i]=1;
dfs(x+1,sum+t[x][i]);
hs[i]=0;
}
}
hs[x]=0;
}
else dfs(x+1,sum);
}
signed main()
{
quick_cin();
cin>>n;
rep2(i,1,n)
rep2(j,1,n)cin>>t[i][j];
dfs(1,0);
cout<<ans;
return 0;
}
最佳调度问题;
if(sum>ans)return;是错误的,会tle,>=都return;有了最小值就return 就i好;
#include<bits/stdc++.h>
//#include<ext/pb_ds/assoc_container.hpp>
#define rep1(i,a,n) for(register ll i=a;i<n;i++)
#define rep2(i,a,n) for(register ll i=a;i<=n;i++)
#define per1(i,n,a) for(register ll i=n;i>a;i--)
#define per2(i,n,a) for(register ll i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define endl "\n"
#define lowbit(x) (-x&x)
using namespace std;
//using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
const int N=1e5+10;
int n,k;
int t[N];
int rob[N];
int ans=INT_MAX;
void dfs(int x,int sum)
{
if(x>n)
{
if(ans>sum)ans=sum;
return ;
}
if(sum>=ans)return;
rep2(i,1,k)
{
if(rob[i]+t[x]<ans)
{
rob[i]+=t[x];
dfs(x+1,max(sum,rob[i]));
rob[i]-=t[x];
}
}
}
signed main()
{
quick_cin();
cin>>n>>k;
rep2(i,1,n)cin>>t[i];
sort(t+1,t+n+1,greater<int>());
dfs(1,0);
cout<<ans;
return 0;
}