Codeforces Round 984 (Div. 3)D-F

D.I Love 1543

思路:

把每一层的拿出看有没有1543,这里可以用dfs,也可以用4次循环,每一边一次。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
//pair<ll,ll> fx[4]={{-1,0},{0,1},{1,0},{0,-1}};
ll an[4]={1,5,4,3};
void solve(){
	ll n,m;cin>>n>>m;
	vector<string> v(n);
	for(ll i=0;i<n;i++)cin>>v[i];
	vector<ll> a;
	vector<vector<bool>> vis((n),vector<bool> (m,false));
	auto dfs=[&](auto &&dfs,ll x,ll y,ll c)->void{
		if(vis[x][y])return;
		a.push_back(v[x][y]-'0');
		vis[x][y]=true;
		ll tx,ty;
		tx==x;
		ty=y;
		if(x==c){
			if(y==m-1-c){
				tx++;
			}else{
				ty++;
			}
		}else if(x==n-1-c){
			if(y==c){
				tx--;
			}else{
				ty--;
			}
		}else if(y==c){
			if(x==c){
				ty++;
			}else{
				tx--;
			}
		}else if(y==m-1-c){
			if(x==n-1-c){
				ty--;
			}else{
				tx++;
			}
		}
		if(vis[tx][ty])return;
		return;
	};
	auto f=[&]()->ll{
		ll res=0;
		ll idx=0;
		for(ll i=0;i<a.size();i++){
			if(a[i]==1){
				idx=i;break;
			}
		}
		ll cnt=0;
		for(ll i=idx,j=0;i<idx+a.size();i++){
			ll t=i%a.size();
			if(a[t]==an[j]){
				j++;
			}else{
				if(a[t]==1){
					j=1;
				}else{
					j=0;
				}
			}
			if(j==4){
				res++;
				j=0;
			}
		}
		return res;
	};
	ll ans=0;
	for(ll c=0;c<min(n/2,m/2);c++){
		a.clear();
		dfs(dfs,c,c,c);
		ans+=f();
	}
	cout<<ans<<endl;
	return;
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	ll _;cin>>_;
	while(_--)solve();
}

E.Reverse the Rivers

思路:

首先我们要知道对于或运算它的结果一定>=前一个数。然后我们就可以先初始化一个范围1~n,然后对于问一次询问通过二分得到新的范围然后求交集。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve(){
    int n,k,q;cin>>n>>k>>q;
	vector<vector<int>> a(n+1,vector<int> (k+1));
	for(int i=1;i<=n;i++){
		for(int j=1;j<=k;j++)cin>>a[i][j];
	}
	for(int i=1;i<=k;i++){
		for(int j=1;j<=n;j++){
			a[j][i]=a[j][i]|a[j-1][i];
		}
	}
	auto f=[&](int &l,int &r,int tl,int tr)->void{
		if(l>r){
			return;
		}
		if(r<tl){
			l=1,r=-1;
			return;
		}
		if(l>tr){
			l=1,r=-1;
			return;
		}
		l=max(l,tl);
		r=min(r,tr);
		return;
	};
	while(q--){
		int m;cin>>m;
		int ans_l=1,ans_r=n;
		for(int i=0;i<m;i++){
			int j;char o;int c;
			cin>>j>>o>>c;
			int l=1,r=n;
			int t=0;
			if(o=='>'){
				while(l<=r){
					int mid=(l+r)/2;
					if(a[mid][j]>c){
						t=mid;
						r=mid-1;
					}else{
						l=mid+1;
					}
				}
				if(t!=0){
					f(ans_l,ans_r,t,n);
				}else{
					ans_l=1;
					ans_r=-1;
				}
			}else{
				while(l<=r){
					int mid=(l+r)/2;
					if(a[mid][j]<c){
						t=mid;
						l=mid+1;
					}else{
						r=mid-1;
					}
				}
				if(t!=0){
					f(ans_l,ans_r,1,t);
				}else{
					ans_l=1;
					ans_r=-1;
				}
			}
		}
		if(ans_l>ans_r){
			cout<<-1<<endl;
		}else{
			cout<<ans_l<<endl;
		}
	}
	return;
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	solve();
}

F.XORificator

思路:

我们要清楚对于对于二进制异或的结果,当前位置1为奇数个时那么最终结果为1,否则为0。所以我们只需要把每一位的1的个数求出来即可。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll f1(ll cnt){
	return (ll)1<<cnt;
}
ll f2(ll cnt){
	return cnt/2;
}
void solve(){
	ll l,r,i,k;cin>>l>>r>>i>>k;
	if(i==0){
		cout<<0<<endl;return;
	}
	vector<ll> cnt(61,0);
	for(ll j=0;j<60;j++){
		ll t=f1(j+1);
		cnt[j]+=(r+1)/t*f2(t)+max((r+1)%t-f2(t),(ll)0);
	}
	for(ll j=0;j<60;j++){
		ll t=f1(j+1);
		cnt[j]-=l/t*f2(t)+max(l%t-f2(t),(ll)0);
	}
	for(ll j=0;j<60;j++){
		if(j<i){
			if(k&f1(j)){
				ll t=f1(i);
				cnt[j]-=(r+1)/t+(((r+1)%t)>k?1:0);
			}
		}else{
			ll t=f1(j+1);
			cnt[j]-=(r+1)/t*f2(t)/f1(i)+max((r+1)%t-f2(t),(ll)0)/f1(i)+((max((r+1)%t-f2(t),(ll)0)%f1(i))>k?1:0);
		}
	}
	for(ll j=0;j<60;j++){
		if(j<i){
			if(k&f1(j)){
				ll t=f1(i);
				cnt[j]+=l/t+((l%t)>k?1:0);
			}
		}else{
			ll t=f1(j+1);
			cnt[j]+=l/t*f2(t)/f1(i)+max(l%t-f2(t),(ll)0)/f1(i)+((max(l%t-f2(t),(ll)0)%f1(i))>k?1:0);
		}
	}
	ll ans=0;
	for(ll j=0;j<60;j++){
		if(cnt[j]%2){
			ans+=f1(j);
		}
	}
	cout<<ans<<endl;
	return;
}

int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	ll _;cin>>_;
	while(_--)solve();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值