11.6NOIP模拟赛

【数据规模和限制】
对于全部测试数据,满足 N,M,K≤100000,W≤1000
各个测试点的数据规模及特殊性质如下表。
测试点 N M K
1101010
2100010001000
3
4100000
5
6100000100000100000
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\n",ans[x]);
    }
    return 0;
}

 

posted @ 2018-11-06 15:39  安月冷  阅读(238)  评论(0编辑  收藏  举报