11.6NOIP模拟赛
【数据规模和限制】 对于全部测试数据,满足 N,M,K≤100000,W≤1000 各个测试点的数据规模及特殊性质如下表。 测试点 N M K 1 ≤10 ≤10 ≤10 2 ≤1000 ≤1000 ≤1000 3 4 ≤100000 5 6 ≤100000 ≤100000 ≤100000 7 8 9 10 师 更多咨询:北京信息学窦老师 QQ3377089232
/* 离散化+树状数组。 */ #include<bits/stdc++.h> #define N 1000007 #define ll long long using namespace std; int n,mod,cnt,tot; ll ans; int a[N],b[N],c[N<<1],ref[N<<1]; 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; } int lowbit(int x){return x&-x;} void Add(int x,int v) { for(;x<=cnt;x+=lowbit(x)) c[x]+=v; } int Query(int x) { int res=0; for(;x;x-=lowbit(x)) res+=c[x]; return res; } ll ksm(ll b,int p) { ll res=1; for(;p;p>>=1,b=b*b%mod) if(p&1)res=res*b%mod; return res; } int Find(int x) { int l=1,r=cnt; while(l<r) { int mid=l+r>>1; if(ref[mid]<x)l=mid+1; else r=mid; }return l; } void Discrete() { sort(ref+1,ref+tot+1); cnt=1; cnt=unique(ref+1,ref+tot+1)-ref-1; for(int i=1;i<=n;i++) a[i]=lower_bound(ref+1,ref+cnt+1,a[i])-ref, b[i]=lower_bound(ref+1,ref+cnt+1,b[i])-ref; } int main() { freopen("calc.in","r",stdin); freopen("calc.out","w",stdout); scanf("%d%d",&n,&mod); int x; for(int i=1;i<=n;i++) { x=read(); a[i]=ksm(i,x);b[i]=ksm(x,i); ref[++tot]=a[i];ref[++tot]=b[i]; } Discrete(); for(int i=1;i<=n;i++) Add(b[i],1); for(int i=1;i<=n;i++) { Add(b[i],-1); ans+=Query(a[i]-1); } cout<<ans<<endl; fclose(stdin);fclose(stdout); return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define inf 0x3f3f3f3f #define ll long long #define N 3001 using namespace std; ll n,m,r,ans,cnt; ll a[N],w[N]; ll k; inline ll read() { ll 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; } ll max(ll a,ll b){return a>b?a:b;} ll check() { ll cur=inf; for(int i=1;i<=n;i++) cur=min(cur,w[i]); return cur; } void update(int now) { for(int i=now-1;i>=max(1,now-r);i--) w[i]++; for(int i=now+1;i<=min(now+r,n);i++) w[i]++; w[now]++; } void back(int now) { for(int i=now-1;i>=max(1,now-r);i--) w[i]--; for(int i=now+1;i<=min(now+r,n);i++) w[i]--; w[now]--; } void dfs(int now,int tot) { if(tot==k) { ans=max(ans,check()); return; } if(now>n) return; dfs(now+1,tot); update(now);dfs(now,tot+1);back(now); update(now);dfs(now+1,tot+1);back(now); } int main() { freopen("game.in","r",stdin); freopen("game.out","w",stdout); n=read();r=read();k=read(); for(int i=1;i<=n;i++) a[i]=read(),ans=min(ans,a[i]); for(int i=1;i<=n;i++) { for(int j=i-1;j>=max(1,i-r);j--) w[j]+=a[i]; for(int j=i+1;j<=min(n,i+r);j++) w[j]+=a[i]; w[i]+=a[i]; } if(n<=10 && r!=0) dfs(1,0),cout<<ans<<endl; else { sort(a+1,a+n+1); int L=1; while(L<n && k) { k-=L*(a[L+1]-a[L]); if(k>=0) ans=a[L+1]; else { ans=a[L]+(k+L*(a[L+1]-a[L]))/L; break; } L++; } if(k) ans+=k/n; cout<<ans<<endl; } fclose(stdin);fclose(stdout); return 0; }
/* 二分加贪心。hkd曾说所有题都能这么做。所以他退役了。 最小值最大,考虑二分答案。 贪心判断可行性,对于每个点,把他向右的范围全加上一个值。 这个操作可以差分。 */ #include<bits/stdc++.h> #define N 1000007 #define ll long long using namespace std; ll n,m,r,k,ans,cnt; ll a[N],b[N],sum[N],opt[N]; inline ll read() { ll 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 ll query(ll L,ll R) { R=min(R,n); if(L<0) return sum[R]; else return sum[R]-sum[L]; } bool check(ll x) { memset(opt,0,sizeof opt); ll now=0,res=k,flag=1; for(int i=1;i<=n;i++) { now+=opt[i];a[i]+=now; if(a[i]<x){now+=x-a[i];opt[i+2*r+1]-=x-a[i];res-=x-a[i];} if(res<0){flag=0;break;} } memcpy(a,b,sizeof a); return flag; } int main() { freopen("game.in", "r", stdin); freopen("game.out", "w", stdout); n=read();r=read();k=read(); for(int i=1;i<=n;i++) a[i]=read(),sum[i]=sum[i-1]+a[i]; for(int i=1;i<=n;i++) b[i]=a[i]=query(i-r-1,i+r); ll L=0,R=3e18,mid; while(L<=R) { mid=(L+R)>>1; if(check(mid)) ans=mid,L=mid+1; else R=mid-1; } cout<<ans<<endl; return 0; }
/* 边从小到大排序后 加边,并查集维护连通性。 注意环的情况。 */ #include<bits/stdc++.h> #define N 100007 using namespace std; int n,m,k; int ans[N],fa[N],siz[N]; struct edge{ int u,v,w,id; }e[N]; bool cmp_w(edge a,edge b){ return a.w<b.w; } 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; } int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} int main() { freopen("graph.in","r",stdin); freopen("graph.out","w",stdout); n=read();m=read();k=read(); for(int i=1;i<=m;i++) { e[i].u=read();e[i].v=read();e[i].w=read(); } sort(e+1,e+m+1,cmp_w); for(int i=1;i<=n;i++) fa[i]=i,siz[i]=0; int maxx=0; for(int i=1;i<=m;i++) { int fax=find(e[i].u); int fay=find(e[i].v); if(fax!=fay) { siz[fay]+=siz[fax]+e[i].w; maxx=max(maxx,siz[fay]); ans[e[i].w]=maxx;fa[fax]=fay; } else { siz[fax]+=e[i].w;ans[e[i].w]=maxx; maxx=max(maxx,siz[fay]); } } for(int i=1;i<=100000;i++) ans[i]=max(ans[i-1],ans[i]); for(int i=1;i<=k;i++) { int x;x=read(); printf("%d\n",ans[x]); } return 0; }
折花枝,恨花枝,准拟花开人共卮,开时人去时。
怕相思,已相思,轮到相思没处辞,眉间露一丝。