Codeforces Round 781 (Div. 2 C树上贪心 D二进制+gcd E结论+线段树)
2023-12-21 19:42:48
A:直接让gcd和lcm都等于1,让a=n-3即可
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+10,mod=998244353,K=5e5;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
const long long inf=1e17;
using node=tuple<int,int,int,int>;
int n,m,k;
int a[N];
void solve()
{
cin>>n;
cout<<n-3<<" "<<1<<" "<<1<<" "<<1<<"\n";
}
signed main()
{
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}
B:
操作题先想操作性质,肯定是操作最多的那个数的
然后操作的时候,无法避免的是都要一个一个从副本换过来
所以换过来是固定次数,然后直接每次换过来之后再复制就行了
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+10,mod=998244353,K=5e5;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
const long long inf=1e17;
using node=tuple<int,int,int,int>;
int n,m,k;
int a[N];
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
map<int,int> mp;
for(int i=1;i<=n;i++) mp[a[i]]++;
sort(a+1,a+1+n,[&](const auto&p,const auto&q){
return mp[p]>mp[q];
});
int res=n-mp[a[1]];
int now=mp[a[1]];
int cnt=0;
while(cnt<n-mp[a[1]])
{
cnt+=now;
now*=2;
res++;
}
cout<<res<<"\n";
}
signed main()
{
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}
C;
可以观察到兄弟节点染色了才能感染其他节点,
所以先统计每个节点的儿子节点
然后按照数量大小去安排感染先后,
这个时候我们发现我们可以得出来感染完全部需要感染节点后,当前节点剩下还需要感染的点,
我们可以通过额外感染加快时间,直接拿个堆去枚举就行了,最多就n次
top是当前每个子树已经同时感染了多少个兄弟节点
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+10,mod=998244353,K=5e5;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
const long long inf=1e17;
using node=tuple<int,int,int,int>;
int n,m,k;
vector<int> g[N],dep[N];
void solve()
{
cin>>n;
vector<int> sz(n+1);
for(int i=1;i<n;i++){
int x;cin>>x;
sz[x]++;
}
sz[0]=1;
sort(sz.begin(),sz.end());
for(int i=0;i<=n;i++){
if(sz[i]==0) continue;
priority_queue<int> q;
for(int j=i;j<=n;j++)
{
q.push(sz[j]-(j-i+1));
}
int ans=n-i+1,top=0;
while(q.top()>top){
top++;
int x=q.top();
q.pop();
q.push(x-1);
ans++;
}
cout<<ans<<"\n";return ;
}
}
signed main()
{
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}
D:
30次,可以去往位运算靠
然后从低位到高位去思考
假设要找当前第 i 位是不是1怎么判断呢
因为我们是从低位到高位去思考,所以当前低位的二进制我们都知道了,我们先减去他
然后当前 i-1到0位的二进制都是0了
我们只需要在第i位去加一个2^i
如果第i位是1,那么就会进位到i+1,否则不会进位,第i位通过我们添加一个2^i后会存在2^i
然后这个时候我们直接去用一个数去判断 当前gcd是不是2^(i)即可,是的话就不是
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10,mod=998244353,K=5e5;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
const long long inf=1e17;
using node=tuple<int,int,int,int>;
int n,m,k;
int a[N];
int ask(int x,int y){
printf("? %lld %lld\n",x,y);
cout.flush();
int z;cin>>z;
return z;
}
void solve()
{
//cin>>n;
int ans=0;
for(int i=1;i<=30;i++){
int x=ask((1<<(i-1))-ans,(1<<i)+(1<<(i-1))-ans);
if(x%(1<<(i))==0)
ans=ans+(1<<(i-1));
}
printf("! %lld\n",ans);
cout.flush();
}
signed main()
{
// cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}
?
E:or的最小值只会出现在区间最小的31个数里面
即区间大小位len ,最小值出现在最小的log(len)+1的数中
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10,mod=998244353,K=5e5;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;
const long long inf=1e17;
using node=tuple<int,int,int,int>;
int n,m,k;
PII tr[N*4];
int a[N];
void modify(int u,int l,int r,int x,int val){
if(l==r) {
tr[u]={val,x};
return ;
}
int mid=l+r>>1;
if(x<=mid) modify(u<<1,l,mid,x,val);
else modify(u<<1|1,mid+1,r,x,val);
tr[u]=min(tr[u<<1],tr[u<<1|1]);
}
pair<int,int> query(int c,int l,int r,int x,int y){
int mid=l+r>>1;
if(l==x&&r==y) return tr[c];
else if(y<=mid) return query(c*2,l,mid,x,y);
else if(x>mid) return query(c*2+1,mid+1,r,x,y);
else return min(query(c*2,l,mid,x,mid),query(c*2+1,mid+1,r,mid+1,y));
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++)
modify(1,1,n,i,a[i]);
cin>>m;
while(m--){
int l,r;
cin>>l>>r;
vector<PII> now;
int lim=min(r-l+1,31ll);
for(int i=1;i<=lim;i++){
now.push_back(query(1,1,n,l,r));
modify(1,1,n,now.back().second,1ll<<31);
}
int mn=1ll<<31;
for(int i=0;i<now.size();i++){
for(int j=i+1;j<now.size();j++)
mn=min(mn,now[i].first|now[j].first);
}
cout<<mn<<"\n";
for(auto [p,v]:now){
modify(1,1,n,v,a[v]);
}
}
}
signed main()
{
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}
文章来源:https://blog.csdn.net/qq_61657632/article/details/135137854
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!