zoukankan      html  css  js  c++  java
  • 【NOIP2011TG】solution

    老师最近叫我把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(n lg 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
    #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

    题意简析:看题目:)

    解题思路:这种数据范围,就是爆搜啊= =,暴力枚举每次交换的点,然后按题意模拟一下,就行了。小剪枝:当任意一种颜色不足3个时就return。时间效率O(能过)。

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.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
    #define mem(qaq,num) memset(qaq,num,sizeof(qaq));
    struct zxy{
        short x,y,op;
    }ans[6];
    short pq[5][7],n;
    inline short in(){
        short 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 swap(short &a,short &b){
        short t=a;a=b,b=t;
    }
    inline void print(int 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);
    }
    void output(){
        For(i,1,n) print(ans[i].x,' '),print(ans[i].y,' '),print(ans[i].op,'
    ');
        exit(0);
    }
    inline void down(){
        For(i,0,4){
            short pos=0;
            For(j,0,6)
                if (pq[i][j]) pq[i][pos++]=pq[i][j];
            For(j,pos,6) pq[i][j]=0;
        }
    }
    inline bool check(){
        For(i,0,4) For(j,0,6) if (pq[i][j]) return 0;
        return 1;
    }
    inline bool move(){
        bool flag=0,used[5][7]={0};
        For(i,0,4)
            For(j,0,6){
                if (i<3&&pq[i][j]==pq[i+1][j]&&pq[i][j]==pq[i+2][j]&&pq[i][j]){
                    used[i][j]=used[i+1][j]=used[i+2][j]=1;
                    flag=1;
                }
                if (j<5&&pq[i][j]==pq[i][j+1]&&pq[i][j]==pq[i][j+2]&&pq[i][j]){
                    used[i][j]=used[i][j+1]=used[i][j+2]=1;
                    flag=1;
                }
            }
        For(i,0,4)
            For(j,0,6)
                if (used[i][j]) pq[i][j]=0;
        return flag;
    }
    inline void dfs(int k){
        if (k>n) if (check()) output(); else return;    
        int memory[5][7],cnt[11]={0};
        For(i,0,4) For(j,0,6) ++cnt[pq[i][j]];
        For(i,1,10) if (cnt[i]<3&&cnt[i]) return;
        memcpy(memory,pq,sizeof(pq));
        For(x,0,3)
            For(y,0,6)
                if(pq[x][y]!=pq[x+1][y]){
                    if (pq[x][y]) ans[k].x=x,ans[k].y=y,ans[k].op=1;
                    else ans[k].x=x+1,ans[k].y=y,ans[k].op=-1;
                    swap(pq[x][y],pq[x+1][y]);
                    down();while(move()) down();
                    dfs(k+1);
                    memcpy(pq,memory,sizeof(pq));
                }
    }
    int main(){
        n=in();
        For(i,0,4){
            short pos=0,x=in();
            while(x) pq[i][pos++]=x,x=in();
        }
        dfs(1);
        printf("-1
    ");
    }

    D2T1:factor

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

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

    #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(nm lg S))的,我们可以发现我们可以通过每次2分后进行一个O(n)的预处理,计算≥W的个数与总和前缀,这样就可以优化效率。时间效率( O((n+m) lg 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,'
    ');
    }
    int main(){
        init();
        solve();
        return 0;
    }

     本文由Melacau编写,Melacau代表M星向您问好,如果您不是在我的博客http://www.cnblogs.com/Melacau上看到本文,请您向我联系,email:13960948839@163.com.

  • 相关阅读:
    Windows10 + eclipse + JDK1.8 + Apache Maven 3.6.0 + dl4j深度学习环境配置
    vector,deque,list的区别和使用
    extern C的用法解析
    向jupyter notebook加入Anaconda3中已添加的虚拟环境kernel
    TensorFlow学习
    windows10+Python3.6+Anaconda3+tensorflow1.10.0配置和安装
    torchvision
    无oracle客户端仅用plsql连接远程oracle
    poj 3463 Sightseeing(次短路+条数统计)
    10.11 noip模拟试题
  • 原文地址:https://www.cnblogs.com/Melacau/p/NOIPTG2011solution.html
Copyright © 2011-2022 走看看