2017.10.25 模拟赛
T1
贪心或二分答案
#include <algorithm> #include <cstring> #include <cctype> #include <cstdio> #define N 100005 using namespace std; int n; struct node { int Ti,Si; bool operator<(node a)const { return Si<a.Si; } }Task[N]; int main() { freopen("manage.in","r",stdin); freopen("manage.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&Task[i].Ti,&Task[i].Si); sort(Task+1,Task+n+1); bool flag=false; int tim=0,ans=0x3f3f3f3f; for(int i=1;i<=n;i++) { if(tim+Task[i].Ti>Task[i].Si) { flag=true; break; } tim+=Task[i].Ti; ans=min(ans,Task[i].Si-tim); } if(flag) puts("-1"); else printf("%d\n",ans); fclose(stdin); fclose(stdout); return 0; }
#include <algorithm> #include <cstdio> inline void read(int &x) { x=0; register char ch=getchar(); for(; ch>'9'||ch<'0'; ) ch=getchar(); for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0'; } const int N(100005); struct Work { int t,s; bool operator < (const Work&x)const { if(s==x.s) return t<x.t; return s<x.s; } }job[N]; int ans=-1,L,R,Mid,n; inline bool check(int x) { for(int i=1; i<=n; ++i) { if(x+job[i].t>job[i].s) return 0; x+=job[i].t; } return 1; } int Presist() { freopen("manage.in","r",stdin); freopen("manage.out","w",stdout); read(n); for(int t,i=1; i<=n; ++i) read(job[i].t),read(job[i].s); std::sort(job+1,job+n+1); for(R=job[1].s-job[1].t+1; L<=R; ) { Mid=L+R>>1; if(check(Mid)) { ans=Mid; L=Mid+1; } else R=Mid-1; } printf("%d\n",ans); return 0; } int Aptal=Presist(); int main(int argc,char**argv){;}
T2
sum[i]为前缀和,num[i]为i颜色的数量
那么i这种颜色对答案的贡献就是C(sum[i]-1,num[i]-1)%mod;
因为i的最后一个不能放到i+1最后一个的前面,所以要减一
分步乘法原理。
#include <cstdio> #include <cctype> #define Mod 998244353 #define N 1000070 typedef long long LL; inline void read(LL &x) { bool f=0;register char ch=getchar(); for(x=0;!isdigit(ch);ch=getchar()) if(ch=='-') f=1; for(;isdigit(ch);x=x*10+ch-'0',ch=getchar()); x=f?-x:x; } LL n,ans=1,num[N],sum[N],f[N],fac[N],inv[N]; void init() { f[0]=inv[0]=fac[0]=f[1]=inv[1]=fac[1]=1; for(LL i=2;i<=N;++i) { fac[i]=(fac[i-1]%Mod*i%Mod)%Mod; f[i]=(Mod-Mod/i)*f[Mod%i]%Mod; inv[i]=(inv[i-1]%Mod*f[i]%Mod)%Mod; } } LL C(LL m,LL n) { if(n>m) return 1; return fac[m]%Mod*inv[n]%Mod*inv[m-n]%Mod; } void print(LL ans) { if(ans/10) print(ans/10); putchar(ans%10+'0'); } int main(int argc,char *argv[]) { freopen("qiang.in","r",stdin); freopen("qiang.out","w",stdout); read(n); for(LL i=1;i<=n;++i) read(num[i]),sum[i]=sum[i-1]+num[i]; init(); for(LL i=2;i<=n;++i) ans=(ans%Mod*C(sum[i]-1,num[i]-1)%Mod)%Mod; print(ans); fclose(stdin); fclose(stdout); return 0; }
T3
题目来源 codechef NOV14.FNCS Chef and Churu
80分 黔驴技穷了 比着std写的 std不知为何 0分啊我也很绝望。
对于每个fi,可以直接使用树状数组求出。
所以我们可以使用分块,中间的直接用块的答案,边上的用树状数组。
首先我们进行预处理,记录第i块中每个编号的个数,这里用前缀和,并求出每个块的和。
对于修改操作1 x y,我们要维护树状数组和块状数组。
树状数组:直接维护。
块状数组:找到每个块中x的个数,这块的sum加上x*(y-a[x])。
最后把a[x]赋成y。
对于查询操作2 x y。
中间的块我们直接用块状数组的答案,O(√n)。
边上的两块我们用树状数组暴力求所有的f[i],O(√n log n)。
所以总的时间复杂度为O(n √n log n)。
#include <algorithm> #include <iostream> #include <cstdio> #include <cctype> #define N 100005 using namespace std; typedef long long LL; inline void read(LL &x) { bool f=0;register char ch=getchar(); for(x=0;!isdigit(ch);ch=getchar()) if(ch=='-') f=1; for(;isdigit(ch);x=x*10+ch-'0',ch=getchar()); x=f?-x:x; } LL tag[N],val[N<<2|1]; int n,q,a[N],x[N],y[N],cnt[N<<2|1],mid[N<<2|1]; struct node { int x,y,id; bool operator<(node a)const { if(x==a.x) return y<a.y; else return x<a.x; } }b[N]; inline int lowbit(int &x) {return x&(-x);} inline void add(int x,int y) {for(;x<=n;x+=lowbit(x)) tag[x]+=y;} inline LL ask(int x) { LL ret=0; for(;x;x-=lowbit(x)) ret+=tag[x]; return ret; } void build(int k,int l,int r) { if(l==r) {val[k]=ask(y[l])-ask(x[l]-1);return;} mid[k]=(l+r)>>1; build(k<<1,l,mid[k]); build(k<<1|1,mid[k]+1,r); val[k]=val[k<<1]+val[k<<1|1]; } void modify(int k,int l,int r,int t) { if(l==r) {val[k]=ask(y[l])-ask(x[l]-1);return;} if(t<=mid[k]) modify(k<<1,l,mid[k],t); else modify(k<<1|1,mid[k]+1,r,t); val[k]=val[k<<1]+val[k<<1|1]; } LL query(int k,int l,int r,int x,int y) { if(l>=x&&r<=y) return val[k]; LL ret=0; if(x<=mid[k]) ret+=query(k<<1,l,mid[k],x,y); if(y>mid[k]) ret+=query(k<<1|1,mid[k]+1,r,x,y); return ret; } int main(int argc,char *argv[]) { freopen("sum.in","r",stdin); freopen("sum.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&a[i]),add(i,a[i]); for(int i=1;i<=n;++i) { scanf("%d%d",&x[i],&y[i]); b[i].x=x[i]; b[i].y=y[i]; b[i].id=i; } build(1,1,n); sort(b+1,b+1+n); scanf("%d",&q); for(int opt,l,r;q--;) { scanf("%d%d%d",&opt,&l,&r); if(opt==1) { add(l,r-a[l]),a[l]=r; for(int i=1;i<=n;++i) { if(b[i].x<=l) modify(1,1,n,b[i].id); else break; } } else cout<<query(1,1,n,l,r)<<"\n"; } fclose(stdin); fclose(stdout); return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #define ll long long #define N 100007 #define S 400 using namespace std; int n,m,unit,num; int fl[N],fr[N],a[N]; int cnt[S][N]; ll ta[N],sumb[S]; inline int read() { int x=0,f=1;char c=getchar(); while(c>‘9‘||c<‘0‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*f; } inline int lowbit(int x){return x&-x;} inline void ins(int i,int add) { for(;i<=n;i+=lowbit(i)) ta[i]+=add; } inline void update(int x,int y) { ins(x,y-a[x]); for(int i=1;i<=num;i++) sumb[i]+=(ll)cnt[i][x]*(y-a[x]); a[x]=y; } inline ll getsum(int i) { ll sum=0; for(;i;i-=lowbit(i)) sum+=ta[i]; return sum; } ll query(int l,int r) { int lblock=(l-1)/unit+1,rblock=(r-1)/unit+1;ll sum=0; if(lblock==rblock) for(int i=l;i<=r;i++) sum+=getsum(fr[i])-getsum(fl[i]-1); else { for(int i=lblock+1;i<=rblock-1;i++) sum+=sumb[i]; for(int i=l;i<=lblock*unit;i++) sum+=getsum(fr[i])-getsum(fl[i]-1); for(int i=(rblock-1)*unit+1;i<=r;i++) sum+=getsum(fr[i])-getsum(fl[i]-1); }return sum; } int main() { freopen("sum.in","r",stdin); freopen("sum.out","w",stdout); n=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) fl[i]=read(),fr[i]=read(); for(int i=1;i<=n;i++) ins(i,a[i]); int nowblock=0; unit=(int)sqrt(n),num=unit+(unit*unit!=n); for(int i=1;i<=n;i++) { if(i%unit==1) nowblock++; cnt[nowblock][fl[i]]++; cnt[nowblock][fr[i]+1]--; } for(int i=1;i<=num;i++) for(int j=1;j<=n;j++) { cnt[i][j]+=cnt[i][j-1]; sumb[i]+=(ll) cnt[i][j]*a[j]; } int k,x,y; m=read(); for(int i=1;i<=m;i++) { k=read();x=read();y=read(); if(k==1) update(x,y); else printf("%I64d\n",query(x,y)); } fclose(stdin);fclose(stdout); return 0; }
我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。