

【数据规模和限制】
对于全部测试数据,满足 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;
}
40暴力
/*
二分加贪心。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
",ans[x]);
}
return 0;
}