IOI2018題解


只有部分題解

練習賽

T2

自然還是要簡單考慮了

0~n-1的排列,考慮相對的大小

 

我們先考慮對於前三個:a,b,c

詢問a,b,詢問b,c,再詢問a,b,c

發現,如果三個知道兩個,那么第三個可以唯一確定

所以分情況討論一下:

1.a>b,不妨欽定a=n-1,然后得到a,b,c的值,再詢問(c,d),(b,c,d)。。。就可以得到所有的值

2.a<b,不妨欽定a=0,然后得到a,b,c的值,再詢問(c,d),(b,c,d)。。。就可以得到所有的值

這里,由於a的值是欽定的,可能得到某個值是負數或者是大於n-1的,那么可以整體上下平移,得到最后的序列

最后的序列中,只要滿足0在n-1左邊,並且是一個0~n-1的排列,那么就是答案(顯然只有一個)

T3

 

可以說是經典的冒泡排序問題!

自然要抓住本質

我們考慮對於一個ai,它歸位的次數就是它前面比它大的數的個數f[i]

證明:前面比它大的數,一次最多沉底一個,然而對於自己往后沉,在后面的bi前比bi小的數那里會考慮到的

所以就是max(f[i])

修改怎么辦?

樹套樹!

兩個logn成功T飛

發現,如果i<j並且ai>aj,那么f[i]一定小於f[j],這樣的i是沒有用的

把剛才的定義變一下:

然后動態開點權值線段樹維護即可(離線離散化也可以不動態開點)

T4

 

更優用bfs O(n^2)判斷(反正提交答案)

Day1

T1

首先,首字母只有一次

詢問AB,如果長度>=1,就是A或者B,再問一次。否則是X或者Y,再問一次。——2次

后面怎么辦?

 

這個長度不超過4n有點意思

首先一定要滿足前綴是S,所以確定的前i-1位必須都有

看來要復制4份,不妨首字母是A

暴力枚舉下一個:[A....BX][A....BY][A.....BB][A....X]

由於首字母只有一次,得到的一定是四個子串的最大匹配長度

如果多了2,就是B;多了1,就是X;不變,就是Y

1次確定一位。

最后一個,需要2次確定,嘗試X,再嘗試Y。

總共:2+(n-2)+2=n+2次

 

T2

 

貼課件:

(這個暫時不懂怎么找那H+W個矩形)

聯通塊的轉化,然后利用點數-邊數最少是1,所以維護最小值和最小值個數即可

聯通塊的轉化很神仙啊

啟示我們,對於一些不好處理的東西,我們提取特征值記錄

這里還利用了最小是1,而1恰好是合法的這一個trick

具體實現的話:

每次把原來的貢獻減掉,新來的再加上

[IOI2018] seats 排座位

T3

kruscal重構樹石錘了

把邊權看成min(idx,idy)(最大生成樹)或者max(idx,idy)(最小生成樹)

就是判斷兩個kruscal重構樹對應的子樹,有沒有交點即可

考慮把每個端點看成二維平面上的一個點,橫坐標是第一個重構樹的位置編號,縱坐標是第二個重構樹位置的編號

有無交點,就是統計(l1,l2,r1,r2)這個矩形中有沒有點

二維數點問題

離線掃描線+樹狀數組解決

掃描線 · 二維數點問題及其應用

(ps:強制在線的話可以用主席樹)

 代碼:

[IOI2018] werewolf 狼人

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
    char ch;x=0;bool fl=false;
    while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
namespace Miracle{
const int M=400000+5;
const int N=400000+5;
const int inf=0x3f3f3f3f;
int n,m,Q;
struct edge{
    int x,y;
    int val;
}b[M];
bool cmp0(edge a,edge b){
    return a.val<b.val;
}
bool cmp1(edge a,edge b){
    return a.val>b.val;
}
int fafa[2*N];

struct kruskal{
    struct node{
        int nxt,to;
    }e[2*N];
    int hd[2*N],cnt;
    int fin(int x){
        return fafa[x]==x?x:fafa[x]=fin(fafa[x]);
    }
    void add(int x,int y){
        e[++cnt].nxt=hd[x];
        e[cnt].to=y;
        hd[x]=cnt;
    }
    int tot;
    void build(int typ){
        for(reg i=1;i<=n;++i){
            if(typ) val[i]=inf;
            else val[i]=-inf;
        }
        tot=n;
        for(reg i=1;i<=m;++i){
            int k1=fin(b[i].x),k2=fin(b[i].y);
    //        cout<<" edge "<<b[i].x<<" "<<b[i].y<<" :: "<<k1<<" "<<k2<<endl;
            if(k1!=k2){
                ++tot;
                fafa[tot]=tot;
                fafa[k1]=tot;
                fafa[k2]=tot;
                val[tot]=b[i].val;
                add(tot,k1);
                add(tot,k2);
            }
        }
    }
    int l[N],r[N];
    int val[N];
    int fa[N][20];
    int df;
    void dfs(int x){
    //    cout<<" xx "<<x<<endl;
        int son=0;
        r[x]=-inf;l[x]=inf;
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            ++son;
            dfs(y);
            fa[y][0]=x;
            r[x]=max(r[x],r[y]);
            l[x]=min(l[x],l[y]);
        }
        if(!son){
            l[x]=r[x]=++df;
        }
    }
    void pre(){
        dfs(tot);
        for(reg j=1;j<=19;++j){
            for(reg i=1;i<=tot;++i){
                fa[i][j]=fa[fa[i][j-1]][j-1];
            }
        }
    }
    int fin(int x,int lim,int typ){//beizeng go val
        int p=x;
        if(!typ){//go <=lim
            for(reg j=19;j>=0;--j){
                if(fa[p][j]){
                    if(val[fa[p][j]]<=lim) p=fa[p][j];
                }
            }
            return p;
        }else{//go >=lim
            for(reg j=19;j>=0;--j){
                if(fa[p][j]){
                    if(val[fa[p][j]]>=lim) p=fa[p][j];
                }
            }
            return p;
        }
    }
}kt[2];//0:min tree;1:max tree;

int num;
struct po{
    int x,y;
    bool friend operator <(po a,po b){
        return a.x<b.x;
    }
}p[N];
int ans[N];

int tot;
struct que{
    int id,x,typ,y1,y2;
    bool friend operator <(que a,que b){
        return a.x<b.x;
    }
}q[N*2];


struct binarytree{
    int f[N];
    void upda(int x){
        for(;x<=n;x+=x&(-x)) f[x]++;
    }
    int query(int x){
        int ret=0;
        for(;x;x-=x&(-x)) ret+=f[x];
        return ret;
    }
}t;
int main(){
    rd(n);rd(m);rd(Q);
    for(reg i=1;i<=m;++i){
        rd(b[i].x);rd(b[i].y);
        
        ++b[i].x;++b[i].y;//warning!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        
        b[i].val=max(b[i].x,b[i].y);
    }
    sort(b+1,b+m+1,cmp0);
    for(reg i=1;i<=2*n;++i){
        fafa[i]=i;
    }
    kt[0].build(0);
    
    kt[0].pre();
//    cout<<" after build small "<<endl;
    for(reg i=1;i<=m;++i){
        b[i].val=min(b[i].x,b[i].y);
    }
    sort(b+1,b+m+1,cmp1);
    for(reg i=1;i<=2*n;++i){
        fafa[i]=i;
    }
    kt[1].build(1);
    kt[1].pre();
    
    int st,nd,L,R;
    for(reg i=1;i<=Q;++i){
        rd(st);rd(nd);rd(L);rd(R);
        ++L;++R;
        ++st;++nd;//warning!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        
        int ptr=kt[1].fin(st,L,1);
        q[++tot].id=i;
        q[tot].y1=kt[1].l[ptr];
        q[tot].y2=kt[1].r[ptr];
        
        q[++tot].id=i;
        q[tot].y1=kt[1].l[ptr];
        q[tot].y2=kt[1].r[ptr];
        
        ptr=kt[0].fin(nd,R,0);
        q[tot-1].x=kt[0].l[ptr]-1;
        q[tot].x=kt[0].r[ptr];
        
        q[tot-1].typ=-1;
        q[tot].typ=1;
    }
    sort(q+1,q+tot+1);
    
    for(reg i=1;i<=n;++i){
        p[i].x=kt[0].l[i];
        p[i].y=kt[1].l[i];
    }
    sort(p+1,p+n+1);
    
    int ptp=1,ptq=1;
    for(reg i=1;i<=n;++i){
        while(ptp<=n&&p[ptp].x<i) ++ptp;
        if(p[ptp].x==i){
            while(ptp<=n&&p[ptp].x==i){
                t.upda(p[ptp].y);
                ++ptp;
            }
        }
        
        while(ptq<=tot&&q[ptq].x<i) ++ptq;
        if(q[ptq].x==i){
            while(ptq<=tot&&q[ptq].x==i){
                ans[q[ptq].id]+=q[ptq].typ*(t.query(q[ptq].y2)-t.query(q[ptq].y1-1));
                ++ptq;
            }
        }
    }
    
    for(reg i=1;i<=Q;++i){
        puts(ans[i]?"1":"0");
    }
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2019/2/10 15:50:00
*/
View Code

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM