AcWing 5589. 哞语言逻辑
大模拟,思路简单,但是实现时要注意代码写的不要混乱,严格执行思路
and优先级高于or,所以可以讲连着的and分成一块,然后统计0,1的数量前缀和,减少时间复杂度
更多细节:视频题解
点击查看代码
#include<bits/stdc++.h>using namespace std;const int maxn=2e5+10;
int q[maxn],id[maxn],l[maxn],r[maxn],cnt=0;
int ones[maxn],zeroes[maxn];
int n,m;
int main(){char str[10];scanf("%d %d",&n,&m);for(int i=1;i<=n;++i){scanf("%s",str);if(!strcmp(str,"true")|| !strcmp(str,"or") ) q[i]=1;if(i&1){if(i==1 || q[i-1]){++cnt;l[cnt]=i;r[cnt-1]=i-2;if(cnt>=2) ones[cnt-1]=ones[cnt-2]+!zeroes[i-2];zeroes[i]=!q[i];}else zeroes[i]=zeroes[i-2]+!q[i];id[i]=cnt;}}r[cnt]=n;ones[cnt]=ones[cnt-1]+!zeroes[n];while(m--){int ll,rr;scanf("%d %d %s",&ll,&rr,str);bool check=!strcmp(str,"true");int lid=id[ll],rid=id[rr];int a=ones[lid-1]+ones[cnt]-ones[rid];int b=zeroes[r[rid]]-zeroes[rr];if(l[lid]!=ll) b+=zeroes[ll-2];if(check==(a||!b && true)|| check==(a||!b && false)) printf("Y");else printf("N");}return 0;
}
AcWing 5590. 沿栅栏散步
乍看有点复杂,但其实适当转化后,思路就很简单,最终的路径会形成一个环,我们任意选择一个起点,沿着形成的路径,记录到达每一步所需的步数.
用二维数组记录每一个坐标对应从起点到该点的步数,由于是环,最后比较,从那一边过来所需的步数最小
点击查看代码
#include<bits/stdc++.h>using namespace std;
#define x first
#define y secondtypedef pair<int,int> pii;
const int maxn=2e5+10;
const int maxm=1e3+10;int s[maxm][maxm];
pii q[maxn];
int n,m;
int get(int x,int tx){if(tx>x) return 1;if(tx<x) return -1;return 0;
}
void solve(){cin>>m>>n;for(int i=1;i<=n;++i)cin>>q[i].x>>q[i].y;int sum=0,x=q[n].x,y=q[n].y;for(int i=1;i<=n;++i){int tx=q[i].x,ty=q[i].y;int vx=get(x,tx),vy=get(y,ty);while(x!=tx || y!=ty){x+=vx,y+=vy;s[x][y]=++sum;}}while(m--){pii a,b;cin>>a.x>>a.y>>b.x>>b.y;int dis=s[b.x][b.y]-s[a.x][a.y];if(dis<0){dis+=sum;} cout<<min(dis,sum-dis)<<endl;}return ;
}
int main(){int t=1;while(t--){solve();}return 0;
}
AcWing 4888. 领导者
分类讨论
其实也就2种情况
对于一个品种的牛要想成为领导者
- 它包含的另一个品种的牛是领导者,当且仅当这个牛满足另一个品种的牛包含其同品种所有牛
- 该牛包含其品种的所有牛,另一个品种的牛也包含其全部同品种牛
点击查看代码
#include<bits/stdc++.h>using namespace std;
int n;
string s;
const int maxn=1e5+10;
int e[maxn];
int rh=0,rg=0;
int lh,lg;
int sh[maxn],sg[maxn];
int ysh=-1,ysg=-1;
int main(){cin>>n>>s;s=" "+s;for(int i=1;i<=n;++i) cin>>e[i];for(int i=1;i<=n;++i){//找出最右边的牛if(s[i]=='H') rh=i;if(s[i]=='G') rg=i;}for(int i=1;i<=n;++i) //检查最左边的牛是否包括所有同品种的牛if(s[i]=='H' ) {lh=i;if(e[i]>=rh) ysh=i;//当前i是包括所有同品种的牛break;}for(int i=1;i<=n;++i){if(s[i]=='G' ) {lg=i;if(e[i]>=rg) ysg=i;break;}}int ans=0;for(int i=1;i<=n;++i){//条件啊if(s[i]=='H')if((ysg>i && e[i]>=ysg ) || (i==lh && rh<=e[i] && ysg>i)) ++ans;if(s[i]=='G')if((ysh>i && e[i]>=ysh ) || (i==lg && rg<=e[i] && ysh>i)) ++ans;}cout<<ans<<endl;return 0;
}
https://www.acwing.com/problem/content/4892/
解法有点花里胡哨,二进制枚举+差分
鉴于范围很小,m台空调就用长度为m的二进制数表示,第i个位置有1,就代表第i个空调打开,所以总的有\(2^m\)个方案,从0枚举到\(2^m-1\)
因为降温都相同,所以可以用差分处理,最后从头开始累加,检验每个位置是否满足要求
点击查看代码
#include<bits/stdc++.h>using namespace std;int n,m;
const int maxn=22;
int stdtem[110];
struct node1{int a,b,p,m;
}kt[maxn];
int quick_pow(int a,int b){int ans=1;while(b){if(b&1) ans*=a;a*=a;b>>=1;}return ans;
}
int main(){cin>>n>>m;for(int i=1;i<=n;++i){int l,r,c;cin>>l>>r>>c;for(int i=l;i<=r;++i) stdtem[i]=max(stdtem[i],c);}for(int i=0;i<m;++i)cin>>kt[i].a>>kt[i].b>>kt[i].p>>kt[i].m;int tot=quick_pow(2,m);int ans=1e9+10;for(int i=1;i<tot;++i){int tem[110],cnt=0;memset(tem,0,sizeof(tem));bitset<20>binary(i);for(int j=0;j<m;++j){if(binary[j]){tem[kt[j].a]+=kt[j].p;tem[kt[j].b+1]-=kt[j].p;cnt+=kt[j].m;}}int now=0;bool book=0;for(int i=1;i<=100;++i){now+=tem[i];if(now<stdtem[i]){book=1;break;}}if(!book) ans=min(ans,cnt);}cout<<ans<<endl;
}
AcWing 4905. 面包店
很有意思,遇到过好几次,不等式求交集
同时你会发现一点,时间越少,一定越能满足客人要求
但是这里有个问题在于有两个变量.
这个时候二分就能妙用,二分减少的总时间z,设减少其中一种制备饼干的时间为x,则另一种减少制备饼干的时间为z-x,解不等式,去检验制备饼干的时间x是否存在,存在则说明z比较还能减小
详细题解
点击查看代码
#include<bits/stdc++.h>using namespace std;
#define ll long long int t;
const int maxn=110;
int n;
int x,y;struct node{ll a,b,c;
}e[maxn];
bool check(ll mid){ll minn=max(0ll,1+mid-y),maxx=min(mid,x-1ll);for(int i=1;i<=n;++i){long double l=e[i].b-e[i].a;long double r=e[i].c-(long double)e[i].a*x-(long double)e[i].b*(y-mid);if(l==0 && r<0) return false;else if(l>0) maxx=min(maxx,(ll)floor(r/l));else if(l<0) minn=max(minn,(ll)ceil(r/l));}return minn<=maxx;
}
void solve(){cin>>n>>x>>y;for(int i=1;i<=n;++i) cin>>e[i].a>>e[i].b>>e[i].c;ll l=0,r=x+y-2;while(l<=r){ll mid=(l+r)>>1;if(check(mid)) r=mid-1;else l=mid+1;}cout<<l<<endl;return ;
}
int main(){cin>>t;while(t--){solve();}return 0;
}