1. 程式人生 > >2018.10.26 NOIP2018模擬賽 解題報告

2018.10.26 NOIP2018模擬賽 解題報告

得分: 0+10+100+10+10T1T1死於假題面,T3T3死於細節… …)

P.S.P.S.由於原題是圖片,所以我沒有上傳題目描述,只有資料。

T1T1:顏料大亂鬥(點此看題面

由於顏色種類數很少,因此比較容易想到將顏色狀壓後線段樹去維護。

但是,題目中沒有提及初始顏色為11,害得我以為初始顏色為00

結果爆00

現將改後的程式碼貼出來:

#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; }

T2T2:妖怪之山(點此看題面

這題是真的噁心。

比賽時有一種情況沒有考慮到,結果寫了三種做法,200+200+行都過不了樣例。

目前訂正到了8080分(純暴力)。

可以考慮O(2k)O(2^k)每一個山洞由誰去訪問,然後對於每一種可能性O(nk)O(nk)驗證(我們就當SPFASPFAO(n)O(n)的),這樣就能水8080分了。

程式碼如下:

#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;
                        }
                    }