1. 程式人生 > >2018年8月13日暑假訓練日記

2018年8月13日暑假訓練日記

昨天學長問我了一個今日頭條的題目,我看著有點像線段樹+二分,今早上就嘗試了一下,但是還沒交,所以不知道對不對,題意大概給定數列a,b求所有區間當中有多少區間滿足a的最大值小於b的最小值,暴力列舉每個區間一定超時,就想到了n^log^log,也就是線段樹+二分,用線段樹處理最大值和最小值的查詢,用二分查詢最大值變更的位置,因為有個性質就是,區間越大,最大值只可能越大,而最小值只可能越小,我們只需要知道這些變更的位置,然後列舉就行了。

#include<iostream>

#include<cstring>

#include<cstdio>

#include<cmath>

#include<algorithm>

#include<vector>

#define maxn 400010

using namespace std;

struct xtree{

    long long l,r;

    long long maxx,minn;

    long long mid(){

        return (l+r)/2;

    }

}atree[maxn],btree[maxn];

struct point{

    long long x;

    long long y;

};

long long a[100010],b[100010];

vector<point>A[100010];

vector<point>B[100010];

void apushup(long long id){

    atree[id].maxx=max(atree[id*2].maxx,atree[id*2+1].maxx);

}

void bpushup(long long id){

    btree[id].minn=min(btree[id*2].minn,btree[id*2+1].minn);

}

void abuild(long long id,long long l,long long r){

    atree[id].l=l;

    atree[id].r=r;

    if (l==r){

        atree[id].maxx=a[l];

        return ;

    }

    long long mid=atree[id].mid();

    abuild(id*2,l,mid);

    abuild(id*2+1,mid+1,r);

    apushup(id);

}

void bbuild(long long id,long long l,long long r){

    btree[id].l=l;

    btree[id].r=r;

    if (l==r){

        btree[id].minn=b[l];

        return ;

    }

    long long mid=btree[id].mid();

    bbuild(id*2,l,mid);

    bbuild(id*2+1,mid+1,r);

    bpushup(id);

}

long long aquery(long long id,long long l,long long r){

    if (atree[id].l>=l&&atree[id].r<=r){

        return atree[id].maxx;

    }

    long long mid=atree[id].mid();

    if (r<=mid){

        return aquery(id*2,l,r);

    }

    else if (l>mid){

        return aquery(id*2+1,l,r);

    }

    else {

        return max(aquery(id*2,l,mid),aquery(id*2+1,mid+1,r));

    }

}

long long bquery(long long id,long long l,long long r){

    if (btree[id].l>=l&&btree[id].r<=r){

        return btree[id].minn;

    }

    long long mid=btree[id].mid();

    if (r<=mid){

        return bquery(id*2,l,r);

    }

    else if (l>mid){

        return bquery(id*2+1,l,r);

    }

    else {

        return min(bquery(id*2,l,mid),bquery(id*2+1,mid+1,r));

    }

}

long long solve(long long n){

    long long i,j,k;

    long long ans=0;

    for (i=1;i<=n;i++){

        long long x=A[i].size();

        long long y=B[i].size();

        k=0;

        long long apla,bpla,amax,bmin;

        long long lasta=i;

        bpla=B[i][k].x;

        bmin=B[i][k].y;

        for (j=0;j<x;j++){

            apla=A[i][j].x;

            amax=A[i][j].y;

            if (amax<bmin){

                if (apla<=bpla){

                    ans+=apla-lasta+1;

                    lasta=apla+1;

                }

                else {

                    ans+=bpla-lasta+1;

                    lasta=bpla;

                    j--;

                    k++;

                    if (k<y){

                        bpla=B[i][k].x;

                        bmin=B[i][k].y;

                    }

                }

            }

            else {

                break;

            }

        }

    }

    return ans;

}

int main(){

    long long n;

    long long i,j;

    while (scanf("%lld",&n)!=EOF){

        for (i=1;i<=n;i++){

            A[i].clear();

            B[i].clear();

        }

        for (i=1;i<=n;i++)scanf("%lld",&a[i]);

        abuild(1,1,n);

        for (i=1;i<=n;i++)scanf("%lld",&b[i]);

        bbuild(1,1,n);

        for (i=1;i<=n;i++){

            for (j=i;j<=n;){

                long long temp=a[j];

                long long l=i,r=n;

                long long ans;

                while (l<=r){

                    long long mid=(l+r)/2;

                    long long fun=aquery(1,i,mid);

                    if (fun<=temp){

                        l=mid+1;

                        ans=mid;

                    }

                    else r=mid-1;

                }

                point p;

                p.x=ans;

                p.y=temp;

                A[i].push_back(p);

                j=ans+1;

            }

        }

        for (i=1;i<=n;i++){

            for (j=i;j<=n;){

                long long temp=b[j];

                long long l=i,r=n;

                long long ans;

                while (l<=r){

                    long long mid=(l+r)/2;

                    long long fun=bquery(1,i,mid);

                    if (fun>=temp){

                        l=mid+1;

                        ans=mid;

                    }

                    else r=mid-1;

                }

                point p;

                p.x=ans;

                p.y=temp;

                B[i].push_back(p);

                j=ans+1;

            }

        }

        long long ans=solve(n);

        cout<<ans<<endl;

    }

}

/*

3

1 2 3

3 3 3

5

1 2 3 4 5

5 5 5 5 5

6

1 1 2 2 3 3

3 3 2 2 1 1

10

1 1 1 1 1 3 3 3 3 3

2 2 2 3 3 3 1 1 1 1

*/

POJ 2187 Beauty Contest(凸包:最遠點對距離):

讓求任意兩點的距離的最大值,這個值一定出現在凸包上,搞出來凸包然後暴力列舉就行了

POJ 1113 Wall(凸包應用):

讓用一個圖形去包裹另一個多邊形(未指定凹凸),,使得周長最小,且距離大於等於L

這時候,計算一個凸包的周長+半徑為L的周長即可

突然想起來還有尺取法這個好東西,這樣應該就不怕變態樣例了:

#include<iostream>

#include<cstring>

#include<cstdio>

#include<cmath>

#include<algorithm>

#include<vector>

#define maxn 400010

using namespace std;

struct xtree{

    long long l,r;

    long long maxx,minn;

    long long mid(){

        return (l+r)/2;

    }

}atree[maxn],btree[maxn];

struct point{

    long long x;

    long long y;

};

long long a[100010],b[100010];

vector<point>A[100010];

vector<point>B[100010];

void apushup(long long id){

    atree[id].maxx=max(atree[id*2].maxx,atree[id*2+1].maxx);

}

void bpushup(long long id){

    btree[id].minn=min(btree[id*2].minn,btree[id*2+1].minn);

}

void abuild(long long id,long long l,long long r){

    atree[id].l=l;

    atree[id].r=r;

    if (l==r){

        atree[id].maxx=a[l];

        return ;

    }

    long long mid=atree[id].mid();

    abuild(id*2,l,mid);

    abuild(id*2+1,mid+1,r);

    apushup(id);

}

void bbuild(long long id,long long l,long long r){

    btree[id].l=l;

    btree[id].r=r;

    if (l==r){

        btree[id].minn=b[l];

        return ;

    }

    long long mid=btree[id].mid();

    bbuild(id*2,l,mid);

    bbuild(id*2+1,mid+1,r);

    bpushup(id);

}

long long aquery(long long id,long long l,long long r){

    if (atree[id].l>=l&&atree[id].r<=r){

        return atree[id].maxx;

    }

    long long mid=atree[id].mid();

    if (r<=mid){

        return aquery(id*2,l,r);

    }

    else if (l>mid){

        return aquery(id*2+1,l,r);

    }

    else {

        return max(aquery(id*2,l,mid),aquery(id*2+1,mid+1,r));

    }

}

long long bquery(long long id,long long l,long long r){

    if (btree[id].l>=l&&btree[id].r<=r){

        return btree[id].minn;

    }

    long long mid=btree[id].mid();

    if (r<=mid){

        return bquery(id*2,l,r);

    }

    else if (l>mid){

        return bquery(id*2+1,l,r);

    }

    else {

        return min(bquery(id*2,l,mid),bquery(id*2+1,mid+1,r));

    }

}

long long solve(long long n){

    long long i,j,k;

    long long ans=0;

    long long s=1;

    long long maxx=a[1];

    long long minn=b[1];

    for (i=1;i<=n;i++){

        if (a[i]>maxx){

            maxx=a[i];

        }

        if (b[i]<minn){

            minn=b[i];

        }

        if (minn<=maxx){

            ans+=i-1-s+1;

            while (minn<=maxx){

                s++;

                if (s>i)break;

                maxx=aquery(1,s,i);

                minn=bquery(1,s,i);

                ans+=i-1-s+1;

            }

        }

    }

    ans+=n-s+1;

    return ans;

}

int main(){

    long long n;

    long long i,j;

    while (scanf("%lld",&n)!=EOF){

        for (i=1;i<=n;i++){

            A[i].clear();

            B[i].clear();

        }

        for (i=1;i<=n;i++)scanf("%lld",&a[i]);

        abuild(1,1,n);

        for (i=1;i<=n;i++)scanf("%lld",&b[i]);

        bbuild(1,1,n);

        long long ans=solve(n);

        cout<<ans<<endl;

    }

}

/*

3

1 2 3

3 3 3

5

1 2 3 4 5

5 5 5 5 5

6

1 1 2 2 3 3

3 3 2 2 1 1

10

1 1 1 1 1 3 3 3 3 3

2 2 2 3 3 3 1 1 1 1

*/

下午比賽暴1了,不想多說,我就是個傻子

快速冪之後我居然用原矩陣計算的結果,一直沒檢查出來,就怎麼一點點錯誤,改了立馬a了,和題解一樣的思路,改了兩個多小時愣是沒發現,完蛋。

樣例太小也是個坑。

#include<iostream>

#include<cstring>

#include<cmath>

#include<iomanip>

#include<algorithm>

#include<cstdio>

#define maxn 1000010

#define mo 1000000007

using namespace std;

struct matrix{

    long long a[11][11],n;

    matrix(long long f,long long size){

        long long i;

        n=size;

        memset (a,0,sizeof(a));

        if (f==0)return ;

        for (i=1;i<=n;i++)a[i][i]=1;

    }

    matrix operator*(const matrix&fun)const{

        matrix ans(0,n);

        long long i,j,k;

        for (i=1;i<=n;i++){

            for (k=1;k<=n;k++){

                if (a[i][k])for (j=1;j<=n;j++){

                    ans.a[i][j]=(ans.a[i][j]+a[i][k]*fun.a[k][j]%mo+mo)%mo;

                }

            }

        }

        return ans;

    }

    matrix qpow(long long x)const{

        int i,j;

        matrix ans(1,n);

        matrix tmp=(*this);

        while (x){

            if (x&1)ans=ans*tmp;

            tmp=tmp*tmp;

            x>>=1;

        }

        return ans;

    }

};

long long a[maxn];

long long b[3];

int main(){

    long long t;

    long long A,B,c,d,p,n;

    long long i,j;

    scanf("%lld",&t);

    while (t--){

        scanf("%lld%lld%lld%lld%lld%lld",&A,&B,&c,&d,&p,&n);

        a[1]=A;

        a[2]=B;

        long long temp=min(n,(long long)1000000);

        for (i=3;i<=temp;i++){

            a[i]=(c*a[i-2]%mo+d*a[i-1]%mo+p/i+mo)%mo;

        }

        if (n==temp)printf("%lld\n",a[n]);

        else {

            temp=p/(p/temp+1);

            long long fun;

            b[1]=a[temp+1];

            b[2]=a[temp+2];

            while (1){

                fun=p/temp-1;

                if (fun){

                    fun=p/fun;

                    long long e=min(n,fun);

                    if (e-temp>2){

                        matrix x(0,3);

                        x.a[1][1]=d;

                        x.a[1][2]=c;

                        x.a[1][3]=p/fun;

                        x.a[2][1]=1;

                        x.a[3][3]=1;

                        matrix ans=x.qpow(e-temp-3);

                        long long ans1=(ans.a[1][1]*b[2]%mo+ans.a[1][2]*b[1]%mo+ans.a[1][3]+mo)%mo;

                        matrix y(0,3);

                        y.a[1][1]=d;

                        y.a[1][2]=c;

                        y.a[1][3]=p/fun;

                        y.a[2][1]=1;

                        y.a[3][3]=1;

                        ans=y.qpow(e-temp-2);

                        long long ans2=(ans.a[1][1]*b[2]%mo+ans.a[1][2]*b[1]%mo+ans.a[1][3]+mo)%mo;

                        if (e==n){

                            printf("%lld\n",(ans2+mo)%mo);

                            break;

                        }

                        else {

                            b[1]=(c*ans1%mo+d*ans2%mo+p/(e+1)+mo)%mo;

                            b[2]=(c*ans2%mo+d*b[1]%mo+p/(e+2)+mo)%mo;

                        }

                        temp=e;

                    }

                    else {

                        if (e-temp==1&&n==e){

                            printf("%lld\n",b[1]);

                        }

                        else {

                            printf("%lld\n",b[2]);

                        }

                    }

                }

                else {

                    long long e=n;

                    matrix x(0,3);

                    x.a[1][1]=d;

                    x.a[1][2]=c;

                    x.a[1][3]=0;

                    x.a[2][1]=1;

                    x.a[3][3]=1;

                    matrix ans=x.qpow(e-temp-2);

                    long long ans1=(ans.a[1][1]*b[2]%mo+ans.a[1][2]*b[1]%mo+ans.a[1][3])%mo;

                    printf("%lld\n",(ans1+mo)%mo);

                    break;

                }

            }

        }

    }

}

/*

5

1 1 2 1 1000000000 1000000000

1 1 2 1 1000000 1000000000

1 1 2 1 1000000000 1000000

1 1 2 1 1000000000 1001000

1 1 2 1 1000000000 1000000

5

1 1 2 1 1000000000 1001000

1 1 2 1 1000000000 999999

*/