zoukankan      html  css  js  c++  java
  • 2018.10.26 NOIP2018模拟赛 解题报告

    得分: \(0+10+10=20\)\(T1\)死于假题面,\(T3\)死于细节... ...)

    \(P.S.\)由于原题是图片,所以我没有上传题目描述,只有数据。

    \(T1\):颜料大乱斗(点此看题面

    由于颜色种类数很少,因此比较容易想到将颜色状压后线段树去维护。

    但是,题目中没有提及初始颜色为\(1\),害得我以为初始颜色为\(0\)

    结果爆\(0\)

    现将改后的代码贴出来:

    #include<bits/stdc++.h>
    #define max(x,y) ((x)>(y)?(x):(y))
    #define min(x,y) ((x)<(y)?(x):(y))
    #define uint unsigned int
    #define LL long long
    #define ull unsigned long long
    #define swap(x,y) (x^=y,y^=x,x^=y)
    #define abs(x) ((x)<0?-(x):(x))
    #define INF 1e9
    #define Inc(x,y) ((x+=(y))>=MOD&&(x-=MOD))
    #define ten(x) (((x)<<3)+((x)<<1))
    #define N 100000
    #define C 30
    using namespace std;
    int n,c;
    class FIO
    {
        private:
            #define Fsize 100000
            #define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
            #define pc(ch) (FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
            int f,FoutSize,OutputTop;char ch,Fin[Fsize],*FinNow,*FinEnd,Fout[Fsize],OutputStack[Fsize];
        public:
            FIO() {FinNow=FinEnd=Fin;}
            inline void read(int &x) {x=0,f=1;while(!isdigit(ch=tc())) f=ch^'-'?1:-1;while(x=ten(x)+(ch&15),isdigit(ch=tc()));x*=f;}
            inline void read_char(char &x) {while(isspace(x=tc()));}
            inline void write(int x) {if(!x) return (void)pc('0');if(x<0) pc('-'),x=-x;while(x) OutputStack[++OutputTop]=x%10+48,x/=10;while(OutputTop) pc(OutputStack[OutputTop]),--OutputTop;}
            inline void write_char(char x) {pc(x);}
            inline void end() {fwrite(Fout,1,FoutSize,stdout);}
    }F;
    class Class_SegmentTree//线段树
    {
        private:
            #define PushUp(x) (node[x].Status=node[x<<1].Status|node[x<<1|1].Status)
            #define PushDown(x) (~node[x].flag&&(node[x<<1].Status=node[x<<1|1].Status=node[x<<1].flag=node[x<<1|1].flag=node[x].flag,node[x].flag=-1))
            struct Tree
            {
                int Status,flag;//Status记录当前区间内颜色状压后的状态,flag为懒惰标记
            }node[N<<2];
            inline void Build(int l,int r,int rt)//建树
            {
                node[rt].Status=2,node[rt].flag=-1;//初始化颜色为1(题面有坑)
                if(!(l^r)) return;
                register int mid=l+r>>1;
                Build(l,mid,rt<<1),Build(mid+1,r,rt<<1|1);
            }
            inline void upt(int l,int r,int rt,int ul,int ur,int val)//修改
            {
                if(ul<=l&&r<=ur) return (void)(node[rt].Status=node[rt].flag=1<<val);//注意懒惰标记
                register int mid=l+r>>1;PushDown(rt);//下推懒惰标记
                if(ul<=mid) upt(l,mid,rt<<1,ul,ur,val);
                if(ur>mid) upt(mid+1,r,rt<<1|1,ul,ur,val);
                PushUp(rt);
            }
            inline int qry(int l,int r,int rt,int ql,int qr)//询问
            {
                if(ql<=l&&r<=qr) return node[rt].Status;
                register int mid=l+r>>1,res=0;PushDown(rt);
                if(ql<=mid) res=qry(l,mid,rt<<1,ql,qr);
                if(qr>mid) res|=qry(mid+1,r,rt<<1|1,ql,qr);//统计信息
                return res;
            }
        public:
            inline void Init() {Build(1,n,1);}
            inline void Update(int l,int r,int v) {upt(1,n,1,l,r,v);}//修改
            inline int Query(int l,int r)//询问
            {
                register int x=qry(1,n,1,l,r),res=0;
                while(x) ++res,x-=(x&-x);//统计答案
                return res;
            }
    }SegmentTree;
    int main()
    {
        register int Q,x,y,z;register char op;
        for(F.read(n),F.read(c),F.read(Q),SegmentTree.Init();Q;--Q)
        {
        	F.read_char(op),F.read(x),F.read(y);
        	if(x>y) swap(x,y);//也是一个坑点,x>y时要交换x,y
        	if(op^'C') F.write(SegmentTree.Query(x,y)),F.write_char('\n');
        	else F.read(z),SegmentTree.Update(x,y,z);
        }
        return F.end(),0;
    }
    

    \(T2\):妖怪之山(点此看题面

    这题是真的恶心。

    比赛时有一种情况没有考虑到,结果写了三种做法,\(200+\)行都过不了样例。

    目前订正到了\(80\)分(纯暴力)。

    可以考虑\(O(2^k)\)每一个山洞由谁去访问,然后对于每一种可能性\(O(nk)\)验证(我们就当\(SPFA\)\(O(n)\)的),这样就能水\(80\)分了。

    代码如下:

    #include<bits/stdc++.h>
    #define max(x,y) ((x)>(y)?(x):(y))
    #define min(x,y) ((x)<(y)?(x):(y))
    #define uint unsigned int
    #define LL long long
    #define ull unsigned long long
    #define swap(x,y) (x^=y,y^=x,x^=y)
    #define abs(x) ((x)<0?-(x):(x))
    #define INF 1e9
    #define Inc(x,y) ((x+=(y))>=MOD&&(x-=MOD))
    #define ten(x) (((x)<<3)+((x)<<1))
    #define N 100
    using namespace std;
    int n,k,v1,v2;
    class FIO
    {
        private:
            #define Fsize 100000
            #define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
            #define pc(ch) (FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
            int f,FoutSize,OutputTop;char ch,Fin[Fsize],*FinNow,*FinEnd,Fout[Fsize],OutputStack[Fsize];
        public:
            FIO() {FinNow=FinEnd=Fin;}
            inline void read(int &x) {x=0,f=1;while(!isdigit(ch=tc())) f=ch^'-'?1:-1;while(x=ten(x)+(ch&15),isdigit(ch=tc()));x*=f;}
            inline void read_char(char &x) {while(isspace(x=tc()));}
            inline void read_string(string &x) {x="";while(isspace(ch=tc()));while(x+=ch,!isspace(ch=tc())) if(!~ch) return;}
            inline void write(int x) {if(!x) return (void)pc('0');if(x<0) pc('-'),x=-x;while(x) OutputStack[++OutputTop]=x%10+48,x/=10;while(OutputTop) pc(OutputStack[OutputTop]),--OutputTop;}
            inline void write_char(char x) {pc(x);}
            inline void write_string(string x) {register int i,len=x.length();for(i=0;i<len;++i) pc(x[i]);}
            inline void end() {fwrite(Fout,1,FoutSize,stdout);}
    }F;
    class Class_BruteForceSolver//暴力
    {
        private:
            int ans,Time[N+5];
            class Class_SPFA//SPFA,我们可以当它是O(n)的
            {
                private:
                    #define add(x,y,z) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].val=z)
                    int ee,lnk[N+5],dis[N+5],Inqueue[N+5];queue<int> q;
                    struct edge
                    {
                        int to,nxt,val;
                    }e[N*N+5];
                public:
                    inline void GetData()//读入数据
                    {
                        register int i,j,x;
                        for(i=1;i<=n;++i) F.read(x),x&&(add(0,i,x),add(i,0,x));
                        for(i=1;i<=n;++i) for(j=1;j<=n;++j) F.read(x),x&&add(i,j,x);
                    }
                    inline int Solve(int s,int t,int v,int *Time)//求s到t的最早时间
                    {
                        register int i,x,dist;
                        for(i=0;i<=n;++i) dis[i]=INF;dis[s]=Time[s],Inqueue[s]=1,q.push(s);//将dis[s]初始化为到达s的时间
                        while(!q.empty())
                        {
                            for(Inqueue[x=q.front()]=0,i=lnk[x],q.pop();i;i=e[i].nxt)
                            {
                                if(e[i].to>t&&e[i].to<=k) continue;
                                if(dist=dis[x]+e[i].val/v,e[i].to<=t&&e[i].to) dist=max(dist,Time[e[i].to-1]);//注意将dist与Time[e[i].to-1]取Max,因为在到达e[i].to-1之前是无法到达e[i].to的
                                if(dist>=dis[e[i].to]) continue;
                                if(dis[e[i].to]=dist,!Inqueue[e[i].to]) q.push(e[i].to),Inqueue[e[i].to]=1;
                            }
                        }
                        return dis[t];
                    }
            }SPFA;
            inline void Operate(int Status)//对该状态操作求解
            {
                register int i,x=0,y=0,t=0,res;
                for(i=1;i<=k;++i) 
                {
                    if(Status&(1<<i-1)) Time[i]=SPFA.Solve(y,i,v2,Time),y=i;
                    else Time[i]=SPFA.Solve(x,i,v1,Time),x=i;
                    if(Time[i]>=ans) return;//剪枝
                }
                ans=Time[k];//更新ans
            }
        public:
            inline void Solve()//求解 
            {
                SPFA.GetData(),ans=INF;
                for(register int i=0,lim=(1<<k)-1;i<=lim;++i) Operate(i);//枚举每个山洞由谁到达
                F.write(ans);
            }
    }BruteForceSolver;
    int main()
    {
        F.read(n),F.read(k),F.read(v1),F.read(v2),BruteForceSolver.Solve();
        return F.end(),0;
    }
    

    \(T3\):上网(点此看题面

    原题: 【洛谷2519】[HAOI2011] problem a

    我发誓, 我真的是死在了细节上。

    我只是手贱在 二分的过程中少打了一个等于号

    然后又手贱把数组开小了。

    于是就只有\(10\)分了... ...

    #include<bits/stdc++.h>
    #define max(x,y) ((x)>(y)?(x):(y))
    #define min(x,y) ((x)<(y)?(x):(y))
    #define uint unsigned int
    #define LL long long
    #define ull unsigned long long
    #define swap(x,y) (x^=y,y^=x,x^=y)
    #define abs(x) ((x)<0?-(x):(x))
    #define INF 1e9
    #define Inc(x,y) ((x+=(y))>=MOD&&(x-=MOD))
    #define ten(x) (((x)<<3)+((x)<<1))
    #define N 500
    #define M 500
    #define K 500000
    using namespace std;
    int n,k,cnt=0,f[N*M+5];
    struct Interval
    {
        int l,r,v;
        Interval(int x=0,int y=0,int z=0):l(x),r(y),v(z){}
        inline friend bool operator < (Interval x,Interval y) {return x.r^y.r?x.r<y.r:x.l<y.l;}
    }s[N*M+5];
    class FIO
    {
        private:
            #define Fsize 100000
            #define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
            #define pc(ch) (FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
            int f,FoutSize,OutputTop;char ch,Fin[Fsize],*FinNow,*FinEnd,Fout[Fsize],OutputStack[Fsize];
        public:
            FIO() {FinNow=FinEnd=Fin;}
            inline void read(int &x) {x=0,f=1;while(!isdigit(ch=tc())) f=ch^'-'?1:-1;while(x=ten(x)+(ch&15),isdigit(ch=tc()));x*=f;}
            inline void read_char(char &x) {while(isspace(x=tc()));}
            inline void read_string(string &x) {x="";while(isspace(ch=tc()));while(x+=ch,!isspace(ch=tc())) if(!~ch) return;}
            inline void write(int x) {if(!x) return (void)pc('0');if(x<0) pc('-'),x=-x;while(x) OutputStack[++OutputTop]=x%10+48,x/=10;while(OutputTop) pc(OutputStack[OutputTop]),--OutputTop;}
            inline void write_char(char x) {pc(x);}
            inline void write_string(string x) {register int i,len=x.length();for(i=0;i<len;++i) pc(x[i]);}
            inline void end() {fwrite(Fout,1,FoutSize,stdout);}
    }F;
    inline int find(int l,int r,int x)//二分出一个最大的res使s[res].r<x,实现O(logN)转移
    {
        for(register int mid=l+r>>1;l<=r;mid=l+r>>1) s[mid].r<x?l=mid+1:r=mid-1;
        return l-1; 
    }
    int main()
    {
        int i,m,x,y,z;
        for(F.read(n),F.read(k),i=1;i<=n;++i) for(F.read(m);m;--m) F.read(x),F.read(y),F.read(z),s[++cnt]=Interval(x,y,z);
        for(sort(s+1,s+cnt+1),i=1;i<=cnt;++i) f[i]=max(f[i-1],f[find(1,i-1,s[i].l)]+s[i].v);//DP转移
        return F.write(f[cnt]),F.end(),0;//输出答案
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    LinkedHashSet的实现原理
    HashSet的实现原理
    HashMap的实现原理
    pl/sql 笔记之存储过程、函数、包、触发器(下)
    pl/sql 笔记之基础(上)
    第三方网站微信登录实现
    kafka connect 创建、删除连接器connector(非常重要!!!!)
    Kafka Connect JDBC-Source 源连接器配置属性
    kafka connect(非常重要)
    kafka connect 使用说明
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Contest20181026.html
Copyright © 2011-2022 走看看