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

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

上午:

HDU 5372 Segment Game(線段樹)

覆蓋區間數=左端點大於L-右端點大於R

由於區間比較大,所以進行離散化處理

然後樹狀陣列維護一下就可以了

The shortest problem(hdu5373+11的倍數)

結論題:能被11整除的數字,奇數和偶數位之和的差可以被11整除。

HDU 5381 The sum of gcd(莫隊+rmq+二分):

由於n比較小先用rmq+二分預處理一下gcd變換的位置

然後莫隊處理區間移動就行了

HDU 5377 Root(擴充套件歐幾里得 + 生成元)

小範圍暴力+大範圍bsgs裸題,因為比較大的質因子只可以有一個

HDU 5386 Cover

逆向思維,在已知結果的前提下看看這個操做是否合法,合法則記錄路徑並更新對應行或者列為任意顏色即可

HDU 5387 Clock

模擬指標的移動就行了,為了防止除不盡,全部擴大120倍在進行處理

下午:

一看1005計算幾何題目有好多人過,找了個假模板搞了兩小時,後來發現就是一個公式,肝到懷疑人生。之後線段樹維護最大值和lazy標記,最後tle,結果賽後改成維護最小值就過了......分析一下應該和資料的隨機性有關係,實際更新次數並不多

上午:

一到比賽就發現線段樹模板沒得用,手敲又種種出錯,所以今天打算看看多校的線段樹題目順便來整理幾套能用的模板,畢竟線段樹是我的專長,老是坑模板有些難受

杭電多校第二場1007 Naive Operations(線段樹七十二變)

  之前做的一道線段樹多校題目,維護b[i]-a[i],和最小值,然後如果需要更新暴力更新到單點,同時樹狀陣列維護sum,當時我的思路和題解完全相同,又是沒有模板不敢敲系列

發現越是像線段樹的題目越是沒有什麼膽量寫,這裡維護標記表示該區間的數是否全部修改為斐波那契數,一個數組表示和這個區間最近的斐波那契數,一個維護與這個值最近的斐波那切數,做一般的區間更新和單點更新即可

HDU 5828 多校第八場 1008 Rikka with Sequence(線段樹--資料加強版)

又是一發線段樹優化,區間更新+區間求sqrt+區間查詢

線段樹的時間複雜度真的是個好東西,一開始看的一個題解,分析了半天最後說這個題目我放棄,也是醉了。

細節多點,不過是個線段樹優化的好題,lazy+cover資料優化+輸入掛可過

標程解法用極差,就是區間最大值和區間最小值,若相同,直接開方,若極差為一,也可以特殊處理。不過更新完需要pushdown一次

hdu6070 二分+線段樹 2017多校第四場1004

其實是個0-1的分數規劃,用線段樹維護一下出現的值就可以了,這裡又一次理解了一下0-1規劃

下午:

這裡求gcd和l,r相同的區間的個數

很巧妙的利用了線段樹的性質,找到了每次gcd的下降的位置,記錄達到加速的目的

單點更新,區間查詢(地兵佈陣):

#include<iostream>

#include<cstring>

#include<cstdio>

#include<cmath>

#include<algorithm>

#define maxn 400010

using namespace std;

struct xtree{

    long long l,r;

    long long sum;

    //long long maxx;

    //long long minn;

    long long mid(){

        return (l+r)/2;

    }

}tree[maxn];

long long a[maxn];

void pushup(long long id){

    tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;

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

    //tree[id].minn=max(tree[id*2].minn,tree[id*2+1].minn);

}

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

    tree[id].l=l;

    tree[id].r=r;

    if (l==r){

        tree[id].sum=a[l];

        //tree[id].maxx=tree[id].minn=a[l];

        return ;

    }

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

    build(id*2,l,mid);

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

    pushup(id);

}

void update(long long id,long long pos,long long val){

    if (tree[id].l==tree[id].r){

        tree[id].sum+=val;

        //tree[id].maxx=tree[id].minn=tree[id].sum;

        return ;

    }

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

    if (pos<=mid){

        update(id*2,pos,val);

    }

    else {

        update(id*2+1,pos,val);

    }

    pushup(id);

}

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

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

        return tree[id].sum;

    }

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

    if (r<=mid){

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

    }

    else if (l>mid){

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

    }

    else {

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

    }

}

int main(){

    long long t;

    long long i,j;

    long long n,m,x,y,z;

    scanf("%lld",&t);

    long long cas=0;

    while (t--){

        scanf("%lld",&n);

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

        build(1,1,n);

        char fun[11];

        printf("Case %lld:\n",++cas);

        while (1){

            scanf("%s",&fun);

            if (fun[0]=='E')break;

            else if (fun[0]=='A'){

                scanf("%lld%lld",&x,&y);

                update(1,x,y);

            }

            else if (fun[0]=='S'){

                scanf("%lld%lld",&x,&y);

                update(1,x,-y);

            }

            else {

                scanf("%lld%lld",&x,&y);

                long long ans=query(1,x,y);

                printf("%lld\n",ans);

            }

        }

    }

}

區間更新,區間查詢(Color the ball):

#include<iostream>

#include<cstring>

#include<cmath>

#include<algorithm>

#include<cstdio>

#define maxn 400010

using namespace std;

struct xtree{

    long long l,r;

    long long lazy;

    long long sum;

    long long mid(){

        return (l+r)/2;

    }

}tree[maxn];

long long a[maxn];

void pushup(long long id){

    tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;

}

void pushdown(long long id){

    if (tree[id].lazy){

        tree[id*2].lazy+=tree[id].lazy;

        tree[id*2+1].lazy+=tree[id].lazy;

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

        tree[id*2].sum+=tree[id].lazy*(mid-tree[id].l+1);

        tree[id*2+1].sum+=tree[id].lazy*(tree[id].r-mid);

        tree[id].lazy=0;

    }

}

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

    tree[id].l=l;

    tree[id].r=r;

    tree[id].lazy=0;

    if (l==r){

        tree[id].sum=0;

        //tree[id].sum=a[l];

        return ;

    }

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

    build(id*2,l,mid);

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

    pushup(id);

}

void update(long long id,long long l,long long r,long long val){

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

        tree[id].lazy+=val;

        tree[id].sum+=(tree[id].r-tree[id].l+1)*val;

        return ;

    }

    pushdown(id);

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

    if (r<=mid){

        update(id*2,l,r,val);

    }

    else if (l>mid){

        update(id*2+1,l,r,val);

    }

    else {

        update(id*2,l,mid,val);

        update(id*2+1,mid+1,r,val);

    }

    pushup(id);

}

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

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

        return tree[id].sum;

    }

    pushdown(id);

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

    if (r<=mid){

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

    }

    else if (l>mid){

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

    }

    else {

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

    }

}

int main(){

    long long n,x,y;

    long long i;

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

        build(1,1,n);

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

            scanf("%lld%lld",&x,&y);

            update(1,x,y,1);

        }

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

            printf("%lld%c",query(1,i,i),i==n?'\n':' ');

        }

    }

}