pyyzDay9
简单的模拟赛(挂大分)
T1

32<=n<=60,T<=1000
考虑直接将数给算出来
判断每一位是否为1
只需要判断当前的数按位与的结果是否为0
注意每次操作完都要更改数值符合sgn数组
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<bits/stdc++.h>
#define int long long
#define jiaa(a,b) {a+=b;if(a>=MOD) a-=MOD;}
#define jian(a,b) {a-=b;if(a<0) a+=MOD;}
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*10+ch-48;ch=getchar();}
return x*f;
}
int sgn[65],a[65],b[65],ans[65],sec[65];
signed main()
{
//freopen("filename.in", "r", stdin);
//freopen("filename.out", "w", stdout);
int n;
cin>>n;
sec[0]=1;
for(int i=1;i<=60;i++) sec[i]=sec[i-1]*2;
for(int i=0;i<n;i++) cin>>sgn[i];
int T;
cin>>T;
while(T--){
for(int i=0;i<n;i++){
cin>>a[i];
ans[i]=0;
}
for(int i=0;i<n;i++) cin>>b[i];
int an=0;
for(int i=0;i<n;i++){
an+=a[i]*sgn[i]*sec[i];
an+=b[i]*sgn[i]*sec[i];
}
for(int i=0;i<n;i++){
if(an&(sec[i+1]-1)){
ans[i]++;
an-=sgn[i]*sec[i];
}
}
for(int i=0;i<n;i++) cout<<ans[i]<<' ';
cout<<'\n';
}
return 0;
}
T2

n,m<=100000
考虑最小生成树是一条链的情况一定不劣
维护相邻点边的minn即可
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<bits/stdc++.h>
#define int long long
#define jiaa(a,b) {a+=b;if(a>=MOD) a-=MOD;}
#define jian(a,b) {a-=b;if(a<0) a+=MOD;}
using namespace std;
int ksm(int a,int b,int p){
if(b==0) return 1;
if(b==1) return a%p;
int c=ksm(a,b/2,p);
c=c*c%p;
if(b%2==1) c=c*a%p;
return c%p;
}
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*10+ch-48;ch=getchar();}
return x*f;
}
struct node{
int l,r,w;
}tr[100005];
int cha[100005];
vector<int> bian[100005];
multiset<int> minn;
signed main()
{
//freopen("filename.in", "r", stdin);
//freopen("filename.out", "w", stdout);
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>tr[i].l>>tr[i].r>>tr[i].w;
cha[tr[i].l]++;
cha[tr[i].r+1]--;
bian[tr[i].l].push_back(tr[i].w);
bian[tr[i].r].push_back(-tr[i].w);
}
for(int i=1;i<=n;i++){
cha[i]+=cha[i-1];
if(!cha[i]){
cout<<-1<<'\n';
return 0;
}
}
int ans=0;
for(int i=1;i<n;i++){
for(auto ed:bian[i]){
if(ed>0) minn.insert(ed);
else minn.erase(minn.find(-ed));
}
ans+=*minn.begin();
}
cout<<ans<<'\n';
return 0;
}
T3

n,m<=200000
考虑类似最短路的做法
发现每条边的边权是可变的
于是记录 dis(ei,u) 表示通过边 ei 到达 u 节点时的最短路径长度
对于两条边a_ex,a_ey,若a_ex<a_ey&&dis(ex,u)<dis(ey,u) 则ey这条边一定无用
具体的,先对每个点能到达的所有点的边权排序
若先后更新的两条边是a_eq,a_qp,只会对边权在a_ep~a_eq之间的产生影响
二分查找两端即可
然后dij
注意松弛操作不超过2次
故复杂度正确
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<bits/stdc++.h>
#define int long long
#define jiaa(a,b) {a+=b;if(a>=MOD) a-=MOD;}
#define jian(a,b) {a-=b;if(a<0) a+=MOD;}
#define pii pair<int,pair<int,int> >
using namespace std;
int ksm(int a,int b,int p){
if(b==0) return 1;
if(b==1) return a%p;
int c=ksm(a,b/2,p);
c=c*c%p;
if(b%2==1) c=c*a%p;
return c%p;
}
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*10+ch-48;ch=getchar();}
return x*f;
}
vector<pii > tu[200005];
priority_queue<pii ,vector<pii >,greater<pii > > hp;
int las[200005],ans[200005];
const int inf=1e16;
signed main()
{
//freopen("filename.in", "r", stdin);
//freopen("filename.out", "w", stdout);
int n=read(),m=read();
for(int i=1;i<=m;i++){
int u=read(),v=read(),a=read(),b=read();
tu[u].push_back({a,{b,v}});
}
for(int i=1;i<=n;i++){
las[i]=ans[i]=inf;
sort(tu[i].begin(),tu[i].end());
}
hp.push({0,{1,inf-1}});
while(!hp.empty()){
int sum=hp.top().first;
int u=hp.top().second.first;
int la=hp.top().second.second;
hp.pop();
ans[u]=min(ans[u],sum);
if(la>=las[u]) continue;
if(las[u]==inf){
for(auto v:tu[u]){
int su=sum;
int a=v.first;
int b=v.second.first;
int ed=v.second.second;
if(a>la) su+=a-b;
else su+=a;
hp.push({su,{ed,a}});
}
}
else{
int l=upper_bound(tu[u].begin(),tu[u].end(),pii{la+1,{0,0}})-tu[u].begin();
for(int i=l;i<tu[u].size();i++){
int a=tu[u][i].first;
int b=tu[u][i].second.first;
int ed=tu[u][i].second.second;
if(a>las[u]) break;
hp.push({sum+a-b,{ed,a}});
}
}
las[u]=la;
}
for(int i=1;i<=n;i++){
if(ans[i]==inf) cout<<-1<<' ';
else cout<<ans[i]<<' ';
}
return 0;
}
T4

n,q<=100000
ai,v<=10000
注意到加减和后缀乘操作都可以被消掉
对答案有贡献的只有前缀连续乘
只需枚举前缀乘的长度
答案贡献为前缀乘积×(2×3^(n-1-len))(后面需要紧接着+/-,其余符号+/-/*)
考虑每次操作
只对i~n的答案有影响
答案变化为乘v/ai(需要逆元)
相当于后缀乘
维护线段树即可
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<bits/stdc++.h>
#define int long long
using namespace std;
int ksm(int a,int b,int p){
if(b==0) return 1;
if(b==1) return a%p;
int c=ksm(a,b/2,p);
c=c*c%p;
if(b%2==1) c=c*a%p;
return c%p;
}
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*10+ch-48;ch=getchar();}
return x*f;
}
void out(int x){
if(x<0)putchar('-'),x=-x;
if(x<10)putchar(x+'0');
else out(x/10),putchar(x%10+'0');
}
int n,m,q,a[100001],ll[500001],rr[500001],tagch[500001],sum[500001],an[500005],thi[100005];
int ls(int x){
return x<<1;
}
int rs(int x){
return x<<1|1;
}
void pushup(int x){
sum[x]=(sum[ls(x)]+sum[rs(x)])%m;
}
void build(int x,int l,int r){
ll[x]=l,rr[x]=r;
tagch[x]=1;
if(l==r){
sum[x]=an[l]%m;
return;
}
int mid=(l+r)>>1;
build(ls(x),l,mid),build(rs(x),mid+1,r);
pushup(x);
}
void tag_cheng(int x,int tag){
(sum[x]*=tag)%=m;
(tagch[x]*=tag)%=m;
}
void pushdown(int x){
if(tagch[x]!=1){
tag_cheng(ls(x),tagch[x]);
tag_cheng(rs(x),tagch[x]);
tagch[x]=1;
}
}
void add_cheng(int x,int L,int R,int k){
if(L<=ll[x]&&rr[x]<=R) return tag_cheng(x,k);
pushdown(x);
int mid=(ll[x]+rr[x])>>1;
if(L<=mid) add_cheng(ls(x),L,R,k);
if(mid<R) add_cheng(rs(x),L,R,k);
pushup(x);
}
int query(int x,int L,int R){
if(L<=ll[x]&&rr[x]<=R) return sum[x];
pushdown(x);
int mid=(ll[x]+rr[x])>>1;
int ret=0;
if(L<=mid) (ret+=query(ls(x),L,R))%=m;
if(mid<R) (ret+=query(rs(x),L,R))%=m;
return ret;
}
signed main(){
cin>>n>>q;
m=1000000007;
for(int i=1;i<=n;i++) cin>>a[i];
thi[0]=1;
for(int i=1;i<=n;i++){
thi[i]=thi[i-1]*3%m;
}
int ch=1;
for(int i=1;i<=n;i++){
ch=ch*a[i]%m;
if(i==n) an[i]=ch;
else an[i]=ch*2%m*thi[n-1-i]%m;
}
build(1,1,n);
while(q--){
int t,v;
cin>>t>>v;
int su=a[t];
su=ksm(a[t],m-2,m);
su=su*v%m;
add_cheng(1,t,n,su);
cout<<query(1,1,n)<<'\n';
a[t]=v;
}
return 0;
}

浙公网安备 33010602011771号