省选模拟3
A. 人脑图灵机
先一直用 \(b\) 然后再看是否大于目标,小于直接 \(No\)
最后看看 \(m \% b\) 的余数,还有剩下的炮弹数
如果剩下的炮弹数大于等于 \(2\) 可以直接 \(Yes\) ,因为两个 \(0.5b\) 可以凑出所有的余数
如果余数小于等于 \(0.5\) 也可以直接 \(Yes\)
那么剩下的情况就是发射一发 \(a\) 了,可以考虑推掉一些 \(b\) 换成 \(a\)
设 \(c=b-a\)
那么这个余数合法当且仅当 \(res+x*c=a\) 同时 \(x\) 小于等于发射的炮弹数
注意一开始的判断会爆,需要用 \(\_\_int128\)
感觉很像 \(CF\) 题
Code
#include<bits/stdc++.h>
#define int __int128
#define rint signed
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int T,n,m,a,b,c,mx,res,w;
inline void solve(){
n=read(),m=read(),a=read(),b=read();c=b-a;
if(b*n<m) return puts("No"),void();
res=m-b*(m/b),w=n-m/b;
if(w>=2) return puts("Yes"),void();
if(!res) return puts("Yes"),void();
if(res<=(b/2)&&w>=1) return puts("Yes"),void();
if(res==a) return puts("Yes"),void();
if((a-res)%c==0&&(a-res)/c<=(m/b)) return puts("Yes"),void();
return puts("No"),void();
}
signed main(){
#ifdef LOCAL
freopen("in","r",stdin);
freopen("out","w",stdout);
#endif
freopen("turing.in","r",stdin);
freopen("turing.out","w",stdout);
T=read();while(T--) solve();
return 0;
}
B. 超脑星球
把每一对 \(a\) 抽象成线段,把 \(b\) 抽象成点,再把他们放到数轴上
再依次考虑增加选择的点数,贪心的考虑一定是从左右两边来进行选择的
所以可以用一个双指针,分别为 \(l,r\)
设线段的左右端点分别为 \(mn,mx\)
对于左边的,然后选择一条线段去匹配,发现贡献分为了两部分,一部分是二倍的到左端点的距离,一部分是线段的长度
那么贡献就是 \(mn-b_l\) ,右边的为 \(b_r-mx\) 都要乘 \(2\)
还有一种情况就是原先跟右边匹配的线段现在去跟左边匹配了
然后我们需要再给原来匹配的点再找一条新的线段
画一下图发现贡献为 \(mn+mx-b_l-mx'\) ,\(mx'\) 为新找的线段
右边也有这样的情况,贡献为 \(b_r-mx-mn-mn'\) ,\(mn'\) 为新找的线段
分别维护一下最值就行,主要到贡献不能为负,因为最次在两个数中间,这个要特判一下
下面两种用了反悔贪心的思路
好像是种套路?叫模拟费用流 UOJ455和这个题感觉很像
Code
#include<bits/stdc++.h>
#define int long long
#define rint signed
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int n,m,l,r;
int a[100010],b[100010];
int ans[100010],c;
struct Seg{int mn,mx;}seg[100010];
set<pair<int,int>>S[5];
bool vis[100010];
signed main(){
#ifdef LOCAL
freopen("in","r",stdin);
freopen("out","w",stdout);
#endif
freopen("brain.in","r",stdin);
freopen("brain.out","w",stdout);
n=read(),m=read();l=1,r=m;
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=m;i++) b[i]=read();sort(b+1,b+1+m);
for(int i=1;i<n;i++) ans[0]+=abs(a[i]-a[i+1]);
for(int i=1;i<n;i++){
seg[i].mn=min(a[i],a[i+1]),seg[i].mx=max(a[i],a[i+1]);
S[1].insert(make_pair(seg[i].mn,i));
S[2].insert(make_pair(seg[i].mx,i));
}
while(l<=r){
int res1=-1,res2=-1,res3=-1,res4=-1,id1=-1,id2=-1,id3=-1,id4=-1;c++;
id1=(*S[1].rbegin()).second;
id2=(*S[2].begin()).second;
if(!S[3].empty()) id3=(*S[3].rbegin()).second;
if(!S[4].empty()) id4=(*S[4].begin()).second;
res1=seg[id1].mn-b[l];
res2=b[r]-seg[id2].mx;
if(id3!=-1) res3=seg[id3].mn+seg[id3].mx-b[l]-seg[id2].mx;
if(id4!=-1) res4=b[r]-seg[id4].mx-seg[id4].mn+seg[id1].mn;
res1*=2;res2*=2;res3*=2;res4*=2;
if(res1>=res2&&res1>=res3&&res1>=res4){
ans[c]=ans[c-1]+res1;l++;
S[1].erase(S[1].find(make_pair(seg[id1].mn,id1)));
S[2].erase(S[2].find(make_pair(seg[id1].mx,id1)));
S[4].insert(make_pair(seg[id1].mn+seg[id1].mx,id1));
}else if(res2>=res1&&res2>=res3&&res2>=res4){
ans[c]=ans[c-1]+res2;r--;
S[1].erase(S[1].find(make_pair(seg[id2].mn,id2)));
S[2].erase(S[2].find(make_pair(seg[id2].mx,id2)));
S[3].insert(make_pair(seg[id2].mn+seg[id2].mx,id2));
}else if(res3>=res1&&res3>=res2&&res3>=res4){
ans[c]=ans[c-1]+res3;l++;
S[1].erase(S[1].find(make_pair(seg[id2].mn,id2)));
S[2].erase(S[2].find(make_pair(seg[id2].mx,id2)));
S[3].insert(make_pair(seg[id2].mn+seg[id2].mx,id2));
S[3].erase(S[3].find(make_pair(seg[id3].mn+seg[id3].mx,id3)));
S[4].insert(make_pair(seg[id3].mn+seg[id3].mx,id3));
}else{
ans[c]=ans[c-1]+res4;r--;
S[1].erase(S[1].find(make_pair(seg[id1].mn,id1)));
S[2].erase(S[2].find(make_pair(seg[id1].mx,id1)));
S[4].insert(make_pair(seg[id1].mn+seg[id1].mx,id1));
S[4].erase(S[4].find(make_pair(seg[id4].mn+seg[id4].mx,id4)));
S[3].insert(make_pair(seg[id4].mn+seg[id4].mx,id4));
}
if(ans[c]<ans[c-1]) ans[c]=ans[c-1];
}
for(int i=1;i<=m;i++) printf("%lld ",ans[i]);
return 0;
}
C. 暗星人
给出的 \(F\) 可以变成前边的维护一个乘法和加法的标记,后边的为取 \(\max\)
发现限制一共两维,于是用数据结构套一下就行,外层维护时间,内层维护 \(L,R\)
这里我用的是分块套线段树
里面查询有个优化就是查询时没有左右儿子就不 \(pushdown\) (虽然因为写假了,并没有起到作用,但还是过了,就不管了
Code
#include<bits/stdc++.h>
#define int long long
#define rint signed
#define lson t[x].ls
#define rson t[x].rs
#define inf 0x3f3f3f3f3f3f3f3f
#define mod 2677114440
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int blo=2500;
int n,m,typ,lst,tot;
int bl[300010],L[125],R[125];
struct node{int l,r,a,b;}T[300010];
struct Seg{
rint ls,rs;
int addtag,multag,mxtag;
}t[65000010];
inline rint newSeg(){tot++;t[tot].addtag=0,t[tot].multag=1,t[tot].mxtag=0;return tot;}
struct BLOCK{
rint rt;
inline void pushdown(rint x){
if(!lson) lson=newSeg();
if(!rson) rson=newSeg();
t[lson].mxtag=max(t[lson].mxtag,t[x].mxtag);
t[rson].mxtag=max(t[rson].mxtag,t[x].mxtag);
t[lson].addtag=(t[lson].addtag*t[x].multag+t[x].addtag)%mod;
t[rson].addtag=(t[rson].addtag*t[x].multag+t[x].addtag)%mod;
t[lson].multag=t[lson].multag*t[x].multag%mod;
t[rson].multag=t[rson].multag*t[x].multag%mod;
t[x].addtag=0,t[x].mxtag=0,t[x].multag=1;
}
void upd(rint &x,int l,int r,int L,int R,int a,int b){
if(!x) x=newSeg();
if(L<=l&&r<=R) return t[x].addtag=(t[x].addtag*a+b)%mod,t[x].multag=t[x].multag*a%mod,t[x].mxtag=max(t[x].mxtag,b),void();
pushdown(x);
int mid=(l+r)>>1;
if(L<=mid) upd(lson,l,mid,L,R,a,b);
if(R>mid) upd(rson,mid+1,r,L,R,a,b);
}
void query(rint x,int l,int r,int pos,int &X,int &Y){
if(!x||l==r) return X=(X*t[x].multag+t[x].addtag)%mod,Y=max(Y,t[x].mxtag),void();
pushdown(x);
int mid=(l+r)>>1;
if(pos<=mid) query(lson,l,mid,pos,X,Y);
else query(rson,mid+1,r,pos,X,Y);
}
#undef lson
#undef rson
}B[125];
inline void ins(int pos){if(R[bl[pos]]==pos) for(int i=L[bl[pos]];i<=R[bl[pos]];i++) B[bl[pos]].upd(B[bl[pos]].rt,1,1000000,T[i].l,T[i].r,T[i].a,T[i].b);}
inline void query(int l,int r,int &x,int &y,int pos){
if(bl[l]==bl[r]){
for(int i=l;i<=r;i++) if(T[i].l<=pos&&pos<=T[i].r){
x=(x*T[i].a+T[i].b)%mod;
y=max(y,T[i].b);
}
return ;
}
for(int i=l;i<=R[bl[l]];i++) if(T[i].l<=pos&&pos<=T[i].r){
x=(x*T[i].a+T[i].b)%mod;
y=max(y,T[i].b);
}
for(int i=bl[l]+1;i<=bl[r]-1;i++) B[i].query(B[i].rt,1,1000000,pos,x,y);
for(int i=L[bl[r]];i<=r;i++) if(T[i].l<=pos&&pos<=T[i].r){
x=(x*T[i].a+T[i].b)%mod;
y=max(y,T[i].b);
}
}
signed main(){
#ifdef LOCAL
freopen("in","r",stdin);
freopen("out","w",stdout);
#endif
freopen("dark.in","r",stdin);
freopen("dark.out","w",stdout);
n=read(),m=read(),typ=read();
for(int i=1;i<=m;i++) bl[i]=(i-1)/blo+1;
for(int i=1;i<=120;i++) L[i]=(i-1)*blo+1,R[i]=min(i*blo,m);
for(int i=1,l,r,pos,x,y;i<=m;i++){
T[i].l=read(),T[i].r=read(),T[i].a=read(),T[i].b=read();
l=read(),r=read(),pos=read(),x=read(),y=0;
if(typ) T[i].l^=lst,T[i].r^=lst,T[i].a^=lst,T[i].b^=lst,l^=lst,r^=lst,pos^=lst,x^=lst;
ins(i);query(l,r,x,y,pos);
printf("%lld\n",lst=(x^y));
}
return 0;
}