NOIP2011TGsolution

Posted Melacau----论一个蒟蒻的自我修养

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP2011TGsolution相关的知识,希望对你有一定的参考价值。

老师最近叫我把NOIPTG的题目给刷掉,于是就开始刷吧= =

链接:https://www.luogu.org/problem/lists?name=&orderitem=pid&tag=83%2C28

D1T1:carpet

题意简析:一个平面内有多个矩形按顺序覆盖平面,问覆盖后某个点属于哪个矩形。

解题思路:从n~1倒着check点有没有在矩形内即可,时间效率O(n)。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#define For(i,a,b) for (int i=a; i<=b; i++)
#define Ford(i,a,b) for (int i=a; i>=b; i--)
#define File(fn) freopen(fn".in","r",stdin); freopen(fn".out","w",stdout);
#define mem(qaq,num) memset(qaq,num,sizeof(qaq));
#define ll long long
#define mod 1000000007
#define INF 2000000000
using namespace std;
struct zxy{
    int a,b,x,y;
}rect[10001];
int n,x,y;
inline int in(){
    int x=0,f=1;
    char ch=getchar();
    while (ch<0||ch>9) f=ch==-?-1:1,ch=getchar();
    while (ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar();
    return x*f;
}
int main(){
    n=in();
    For(i,1,n)
        rect[i].a=in(),rect[i].b=in(),rect,rect[i].x=in()+rect[i].a,rect[i].y=in()+rect[i].b;
    x=in(),y=in();
    Ford(i,n,1){
        if (x>=rect[i].a&&x<=rect[i].x&&y>=rect[i].b&&y<=rect[i].y){
            printf("%d",i);
            return 0;
        }
    }
    printf("-1");
}

 

D1T2:hotel

题意简析:给你n个客栈,叫你选取任意2个色调相同的不同客栈,且它们之间(包括本身)所有的客栈内存在最低消费不超过p的咖啡店,问你有多少种方案。

解题思路:这题貌似有O(n)的算法,但是我只想到O(n^2)的贪心,然后用线段树存区间最小值优化一个log,然后存下不同色调的客栈数,顺推一下就行了。时间效率O(nlog2n).

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#define For(i,a,b) for (int i=a; i<=b; i++)
#define Ford(i,a,b) for (int i=a; i>=b; i--)
#define File(fn) freopen(fn".in","r",stdin); freopen(fn".out","w",stdout);
#define mem(qaq,num) memset(qaq,num,sizeof(qaq));
#define ll long long
#define mod 1000000007
#define INF 2000000000
#define mid ((l+r)>>1)
using namespace std;
int mi[600000],color[50][200000],cnt[50],lst[50],n,k,p;
inline int in(){
    int x=0,f=1;
    char ch=getchar();
    while (ch<0||ch>9) f=ch==-?-1:1,ch=getchar();
    while (ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar();
    return x*f;
}
inline void update(int x,int k,int l,int r,int add){
    if (l==r) {
        mi[k]=add;
        return;
    }
    if (x<=mid) update(x,k<<1,l,mid,add);
    else update(x,k<<1|1,mid+1,r,add);
    mi[k]=min(mi[k<<1],mi[k<<1|1]);
}
inline int query(int l,int r,int k,int a,int b){
    if (!(l^a||r^b)) return mi[k];
    if (b<=mid) return query(l,mid,k<<1,a,b);
    if (a>mid) return query(mid+1,r,k<<1|1,a,b);
    return min(query(l,mid,k<<1,a,mid),query(mid+1,r,k<<1|1,mid+1,b));
}
int main(){
    mem(mi,127/3);
    n=in(),k=in(),p=in();
    For(i,1,n){
        int cl=in(),x=in();
        color[cl][++cnt[cl]]=i;
        update(i,1,1,n,x);
    }
    ll ans=0;
    For(i,0,k-1)
        For(j,2,cnt[i]){
            if (query(1,n,1,color[i][j-1],color[i][j])<=p) ans+=j-1,lst[i]=j-1;
            else ans+=lst[i];
        }
    printf("%lld",ans);
}

 

D1T3:mayan(待更新)

D2T1:factor

题意简析:就是题目要求的啊。

解题思路:把ax和by看成整体,杨辉三角形求完全k次方式的各项系数,然后再用ax和by代进去就行了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#define For(i,a,b) for (int i=a; i<=b; i++)
#define Ford(i,a,b) for (int i=a; i>=b; i--)
#define File(fn) freopen(fn".in","r",stdin); freopen(fn".out","w",stdout);
#define mem(qaq,num) memset(qaq,num,sizeof(qaq));
#define ll long long
#define mod 10007
#define INF 2000000000
using namespace std;
int tri[1002][1002],n,m,k,a,b;
inline int in(){
    int x=0,f=1;
    char ch=getchar();
    while (ch<0||ch>9) f=ch==-?-1:1,ch=getchar();
    while (ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar();
    return x*f;
}
inline int ksm(int a,int k){
    if (!k) return 1;
    if (!(k^1)) return a%mod;
    int ans=ksm(a,k/2)%mod;
    if (k&1) return ans*ans%mod*a%mod;
    return ans*ans%mod;
}
int main(){
    a=in()%mod,b=in()%mod,k=in(),n=in(),m=in();
    tri[1][1]=1;
    For(i,2,k+1)
        For(j,1,i)
            tri[i][j]=(tri[i-1][j-1]+tri[i-1][j])%mod;
    printf("%d",ksm(a,n)*ksm(b,m)%mod*tri[k+1][k-n+1]%mod);
}

 

D2T2:qc

题意简析:叫你确定一个参数W按照公式计算后使得|S-∑y[i]|最小。

解题思路:显然对于W的递增,有∑y[i]单调递减,我们考虑二分W,然后进行check。这样的效率是O(nmlogS)的,我们可以发现我们可以通过每次2分后进行一个O(n)的预处理,计算≥W的个数与总和前缀,这样就可以优化效率。时间效率O((n+m)log2(max(W[i])))

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#define For(i,a,b) for (int i=a; i<=b; i++)
#define Ford(i,a,b) for (int i=a; i>=b; i--)
#define File(fn) freopen(fn".in","r",stdin); freopen(fn".out","w",stdout);
#define mem(qaq,num) memset(qaq,num,sizeof(qaq));
#define mod 1000000007
#define INF 1e18
#define mid (l+r>>1)
using namespace std;
int cnt[200001],sum[200001],w[200001],n,m,ll[200001],rr[200001],maw,miw=0x7fffffff,v[200001];
long long s,ans=1e18;
template <class T>
inline void in(T &x){
    x=0;
    short f=1;
    char ch=getchar();
    while (ch<0||ch>9) f=ch==-?-1:1,ch=getchar();
    while (ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar();
    x*=f;
}
void init(int k){
    cnt[0]=sum[0]=0;
    For(i,1,n)
        if (w[i]>=k){
            cnt[i]=cnt[i-1]+1;
            sum[i]=sum[i-1]+v[i];
        }
        else cnt[i]=cnt[i-1],sum[i]=sum[i-1];
    return;
}
inline void BS(int l,int r){
    if (l>r) return;
    init(mid);
    long long tmp=0;
    For(i,1,m){
        tmp+=abs((long long)((cnt[rr[i]]-cnt[ll[i]-1])*(sum[rr[i]]-sum[ll[i]-1])));
        if (tmp>INF) break;
    }
    if (tmp==s){
        ans=0;
        return;
    }
    if (tmp<s){
        if (s-tmp<ans){
            ans=s-tmp;
        }
        BS(l,mid-1);
        return;
    }
    if (tmp-s<ans){
        ans=tmp-s;
    }
    BS(mid+1,r);
}
int main(){
    in(n); in(m); in(s);
    For(i,1,n)
        in(w[i]),in(v[i]),miw=miw>w[i]?w[i]:miw,maw=maw<w[i]?w[i]:maw;
    For(i,1,m)
        in(ll[i]),in(rr[i]);
    BS(miw,maw);
    printf("%lld",ans);
}

 

D2T3:bus

题意:就是一条链,每个点之间有限定条件,叫你求权值最小是多少。

解题思路:枚举每个加速器放在哪里,用前缀和优化找出对于可能的加速可以减少多少等待时间即可。时间效率O(kn)。(貌似有O(n)的算法)

#include<stdio.h>
#define For(i,a,b) for (int i=a; i<=b; i++)
#define Ford(i,a,b) for (int i=a; i>=b; i--)
#define File(fn) freopen(fn".in","r",stdin); freopen(fn".out","w",stdout);
#define ll long long
#define mod 1000000007
#define INF 2000000000
int n,m,k,num[1001],st[1001],tim[1001],dis[1001],ans,use[1001]; 
struct zxy{
    int a,b,t;
}tou[10001];
template <class T>
inline void in(T &x){
    x=0;
    short 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-0,ch=getchar();
    x*=f;
}
template <class T>
inline void print(T x,char ch){
    if (!x){
       putchar(0);
       putchar(ch);
       return;
    }
    if (x<0){
       putchar(-);
       x*=-1;
    }
    char num[20];
    short cnt=0;
    while(x) num[++cnt]=x%10+0,x/=10;
    while(cnt) putchar(num[cnt--]);
    putchar(ch);
}//for integer only
template <class T>
inline T max(T a,T b){
    return a>b?a:b;
}
template <class T>
inline T min(T a,T b){
    return a<b?a:b;
}
template <class T>
inline void abs(T &x){
    x=x<0?-x:x;
}
void init(){
    in(n),in(m),in(k);
    For(i,1,n-1) in(dis[i]);
    For(i,1,m)
        in(tou[i].t),in(tou[i].a),in(tou[i].b),num[tou[i].b]++,st[tou[i].a]=max(tou[i].t,st[tou[i].a]);
    For(i,2,n) num[i]+=num[i-1];
    tim[1]=0;
    For(i,2,n)
        tim[i]=max(tim[i-1],st[i-1])+dis[i-1];
    For(i,1,m)
        ans+=tim[tou[i].b]-tou[i].t;
}
void solve(){
    while(k){
        use[n]=use[n-1]=n;  
        Ford(i,n-2,1)
            use[i]=tim[i+1]<=st[i+1]?i+1:use[i+1];
        int np=0,p;
        For(i,1,n)
            if (num[use[i]]-num[i]>np&&dis[i])
                np=num[use[i]]-num[i],p=i;
        if (!np) break;
        ans-=np;
        dis[p]--;
        k--;
        tim[1]=0;
        For(i,2,n)
            tim[i]=max(tim[i-1],st[i-1])+dis[i-1];
    }
    print(ans,\n);
}
int main(){
    init();
    solve();
    return 0;
}

 

以上是关于NOIP2011TGsolution的主要内容,如果未能解决你的问题,请参考以下文章

NOIP2016TGsolution

NOIP2013TGsolution

NOIp 2011 mayan游戏 搜索

[NOIP2011]聪明的质监员 题解

[NOIP2011]观光公交 题解

P1307 [NOIP2011 普及组] 数字反转