Pinely Round 4 (Div. 1 + Div. 2)

A.枚举:https://codeforces.com/contest/1991/problem/A

可以取到的都是奇数位:

#include<bits/stdc++.h>
using namespace std;
int t,n;
int a[110];
int main(){
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=1;i<=n;i++) cin>>a[i];
		int maxx=0;
		for(int i=1;i<=n;i+=2) maxx=max(maxx,a[i]);
		cout<<maxx<<endl;
	}
}

B.构造,位运算:https://codeforces.com/contest/1991/problem/B

在首尾之间最优解是b[i]=a[i]|a[i-1]:

AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    int t,n;
    int b[100100],a[100010];
    int main(){
    	cin>>t;
    	while(t--){
    		cin>>n;
    		for(int i=1;i<=n-1;i++) cin>>b[i];
    		for(int i=2;i<=n-1;i++){
    			a[i]=b[i]|b[i-1];
    		}
    		a[1]=b[1];
    		a[n]=b[n-1];
    		int f=0;
    		for(int i=1;i<=n-1;i++){
    			if((a[i]&a[i+1])==b[i]) continue;
    			f=1;
    			break;
    		}
    		if(f==1) cout<<-1<<endl;
    		else{
    			for(int i=1;i<=n;i++) cout<<a[i]<<" ";
    			cout<<endl;
    		}
    	}
    }

C.构造:https://codeforces.com/contest/1991/problem/C

首先:通过操作无法改变任意两个数的相对奇偶性,也就是假如有一奇一偶,那么他们奇偶性一定不同,最后也就无法都化为0.

至于剩下的情况,我们不妨可以取他们的max与min,我们要让他们归0,也就一定要让他们变一样,这个问题等价于max=min,于是我们每次都取他们的平均数,这样就可以以指数级别递减。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t,n,a[200010];
ll cnt;
ll b[200010];
int kk;
ll res[200010];
int main(){
	cin>>t;
	while(t--){
		cin>>n;
		cnt=0;
		for(int i=1;i<=n;i++) cin>>a[i];
		set<ll> s;
		for(int i=1;i<=n;i++) s.insert(a[i]);
		int k[2]={0};
		for(auto c=s.begin();c!=s.end();c++){
			b[++cnt]=*c;
		}
		for(int i=1;i<=cnt;i++) k[b[i]%2]=1;
		if(k[0]&&k[1]){
			cout<<-1<<endl;
			continue;
		}
		ll l,r;
		kk=0;
		while(1){
		    l=1e9,r=0;
			for(int i=1;i<=cnt;i++) l=min(b[i],l);
			for(int i=1;i<=cnt;i++) r=max(r,b[i]);
			if(l==0&&r==0) break;
			int mid=(l+r)/2;
			res[++kk]=mid;
			for(int i=1;i<=cnt;i++) b[i]=abs(mid-b[i]);
		}
		cout<<kk<<endl;
		for(int i=1;i<=kk;i++){
			cout<<res[i]<<" ";
		}
		cout<<endl;
	}
}

D.构造/思维:https://codeforces.com/contest/1991/problem/D

不得不说,这一题还是很考验大家观察力的。

首先n\geqslant 6,一定是需要4种的(因为1,3,4,6互连)

其次,我们只用4种,我们考虑把下标i的染成第i%4+1

证明:对于同色的都可以表示为4*a+k,4*b+k,因此他们二进制串的前两位表示的就是k,因此异或一定会变成0,也就是他们异或值是最小权值是4,因此一定是4的倍数,也就不是质数。

AC代码:

#include <bits/stdc++.h>
using namespace std;
void solve() {
    int n;
    cin >> n;
    if (n < 6) {
        if (n == 1)
            cout << 1 << '\n' << "1" << endl;
        else if (n == 2)
            cout << 2 << '\n' << "1 2" << endl;
        else if (n == 3)
            cout << 2 << '\n' << "1 2 2" << endl;
        else if (n == 4)
            cout << 3 << '\n' << "1 2 2 3" << endl;
        else if (n == 5)
            cout << 3 << '\n' << "1 2 2 3 3" << endl;
    } else {
        cout << 4 << '\n';
        for (int i = 1; i <= n; i++)
            cout << i % 4 + 1 << ' ';
        cout << endl;
    }
}
int main() {
    int t;
    cin >> t;
    while (t--)
        solve();
}

E.构造/二分图:https://codeforces.com/contest/1991/problem/E

1.假如不为二分图,Alice的必胜策略就是每次都说1或者2.

2.假如为二分图,Bob的必胜策略就是在两个颜色中挑1/2放在他们各自染色的地方,当某个(1或者2,这里假设1)填满时,假如又是(1,3),那么就选3去填2剩下的部分。显然这不会存在同色同边的情况。

F.枚举,构造,贪心:https://codeforces.com/contest/1991/problem/F

首先,我们不妨看看只求一个三角形:排个序,然后找连续3个是否可以组成。

而换成两个三角形:我们通过模拟得出规则

我们排好序,任意取出A...B...C...D...E...F,我们看看是否可以组成两个三角形:

我们先假设空格

显然,每一个三角形的最长边在CDEF中选:

每一个优化可以看出被“吸”过去

1.我们取C为最长边,那么就是ABC,DEF,而我们发现AB,DE可以优化为C/F前面的连续两个,也就是ABC...DEF

2,我们取D为最长边,我们假设A不属于D(其他同理),于是就是BCD,AEF,显然我们把BC优化成D的前面两个,AE优化成F前两个(前面有阻挡那就只可以保持现在了)

3.选EF也是同一道理。

因此:1.我们先扫一下是否有两个不交的3元素区间满足。

            2.再枚举连续6个元素的区间。    

AC代码:

#include<bits/stdc++.h>
using namespace std;
int n,q,fk;
int a[100010];
int rt[7];
bool vis[7];
bool ans;
void checkk(){
	int A1,A2,zhi1,zhi2;
	for(int i=6;i>=1;i--){
		if(vis[i]==1){
			A1=i;
			break;
		}
	}
	for(int i=6;i>=1;i--){
		if(vis[i]==0){
			A2=i;
			break;
		}
	}
	zhi1=rt[A1],zhi2=rt[A2]; 
	for(int i=A1-1;i>=1;i--){
		if(vis[i]==1) zhi1-=rt[i];
	}
	for(int i=A2-1;i>=1;i--){
		if(vis[i]==0) zhi2-=rt[i];
	}
	if(zhi1<0&&zhi2<0) ans=1;
}
void dfs(int u,int st)//u:选了u个到组1,从st开始 
   {
   		
		if(u==3){
			checkk();
			return;
		}
		if(st>=7) return;
		for(int i=st;i<=6;i++){
			vis[st]=1;
			dfs(u+1,i+1);
			vis[st]=0;
		}
   }

bool check(int l,int r){
	int ck[60]={0};
	int cnt=0;
	for(int i=l;i<=r;i++){
		ck[++cnt]=a[i];
	}
	sort(ck+1,ck+cnt+1);
	//分开的3个
	int minn=100,maxx=-1;
	for(int i=1;i<=cnt-2;i++){
		if(ck[i]+ck[i+1]>ck[i+2]){
			minn=min(minn,i);
			maxx=max(maxx,i);
		}
	} 
	if(minn+3<=maxx) return 1;
	//连续
	for(int i=1;i<=cnt-5;i++){
		ans=0;
		for(int j=i;j<=i+5;j++) rt[j-i+1]=ck[j];
		dfs(0,1);
		if(ans) return 1;
	} 
	return 0;
}
int main(){
	cin>>n>>q;
	for(int i=1;i<=n;i++) cin>>a[i];
	while(q--){
		int l,r;
		cin>>l>>r;
		if(r-l+1>=48) cout<<"YES"<<endl;
		else{
			if(check(l,r)==1) cout<<"YES"<<endl;
			else cout<<"NO"<<endl;
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值