1. 程式人生 > >18寒假第六測

18寒假第六測

格子 bound mage spa query 標記 std image build

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

第一題:乘法修改的線段樹

  一定不能將change,modify分類討論定兩個標記,會有順序影響

  lazy標記一定要long long,又忘了。。。

代碼和上一次差不多

第二題:離散暴力,也可以掃描線

  離散時要將格子映射成點,不然會出現以下情況:

  算橫著的小矩形寬就是2,算黃色面積寬還是2,因為沒有2讓3去減

技術分享圖片

  如果映射成點,就像這樣,,放圖比較好理解,就像掃描線,一個葉子節點存的是一個左閉右開的區間

技術分享圖片

也可以離散+掃描線,但還沒寫出來

#include <bits/stdc++.h>

using namespace std;
#define maxn 1005
int
disx[maxn*2],disy[maxn*2],xs[maxn*2],xe[maxn*2],ys[maxn*2],ye[maxn*2]; int totx,toty; bool st[maxn*2][maxn*2]; void read(int &x){ int f=1;x=0;char s=getchar(); while(s<0||s>9){if(s==-)f=-1;s=getchar();} while(s>=0&&s<=9){x=x*10+s-0;s=getchar();} x*=f; }
int main() { freopen("area.in","r",stdin); freopen("area.out","w",stdout); int n; read(n); for(int i = 1; i <= n; i++){ read(xs[i]),read(ys[i]),read(xe[i]),read(ye[i]); xs[i]-=1,ys[i]-=1; disx[++totx]=xs[i],disx[++totx]=xe[i]; disy[++toty]=ys[i],disy[++toty]=ye[i]; } sort(disx
+ 1, disx + 1 + totx); sort(disy + 1, disy + 1 + toty); totx = unique(disx + 1, disx + 1 + totx) - disx - 1; toty = unique(disy + 1, disy + 1 + toty) - disy - 1; for(int k = 1; k <= n; k++){ int xn = lower_bound(disx + 1, disx + 1 + totx, xs[k]) - disx; int xm = lower_bound(disx + 1, disx + 1 + totx, xe[k]) - disx; int yn = lower_bound(disy + 1, disy + 1 + toty, ys[k]) - disy; int ym = lower_bound(disy + 1, disy + 1 + toty, ye[k]) - disy; for(int i = xn+1; i <= xm; i++) for(int j = yn+1; j <= ym; j++) st[i][j] = 1; } long long ans = 0; for(int i = 1; i <= totx; i++) for(int j = 1; j <= toty; j++) if(st[i][j]) ans += 1LL * (disx[i] - disx[i - 1]) * (disy[j] - disy[j - 1]); printf("%I64d\n",ans); return 0; }

第三題:可持久化數組,每次建樹logN的空間復雜度,不改變原來的版本

pool大小為N*2+Q*logN,Q為詢問次數

#include <bits/stdc++.h>

using namespace std;
#define maxn 100005
#define ll long long
int a[maxn],n,m,s;
void read(int &x){
    int f=1;x=0;char s=getchar();
    while(s<0||s>9){if(s==-)f=-1;s=getchar();}
    while(s>=0&&s<=9){x=x*10+s-0;s=getchar();}
    x*=f;
}

struct Node{
    int v;
    Node *ls, *rs;

}pool[maxn * 32],*tail = pool, *root[maxn];//?

Node * build(int l = 1,int r = n){
    Node *nd = ++tail;
    if(l == r)
        nd->v = a[l];
    else {
        int m = (l + r) >> 1;
        nd->ls = build(l, m);
        nd->rs = build(m + 1, r);
    }
    return nd;
}
#define Ls nd->ls, l, m
#define Rs nd->rs, m+1, r
Node * modify(int delta, int pos, Node *nd, int l = 1, int r = n){
    Node *nnd = ++tail;
    if(l == r) nnd->v = delta;
    else {
        int m = (l + r) >> 1;
        if(pos <= m){
            nnd->rs = nd->rs;
            nnd->ls = modify(delta, pos, Ls);

        }
        if(pos > m){
            nnd->ls = nd->ls;
            nnd->rs = modify(delta, pos, Rs);
        }
    }
    return nnd;
}

int query(int pos, Node *nd, int l = 1, int r = n ){
    if(l == r)
      return nd->v;
    else {
        int m = (l + r) >> 1;
        if(pos <= m)return query(pos, Ls);
        else return query(pos, Rs);
    }
}
Node * print(int pos,Node *nd){
    printf("%d\n",query(pos,nd));
    return nd;
}
int main(){
    freopen("array.in","r",stdin);
    freopen("array.out","w",stdout);
    read(n);
    for(int i = 1; i <= n; i++)
        read(a[i]);
    root[0] = build();
    read(m);
    for(int i = 1; i <= m; i++){
        string opt;
        cin>>opt;
        if(opt[0] == q){
            int pos;
            read(pos);
            root[i] = print(pos, root[i - 1]);
        }
        else if(opt[0] == m){
            int pos, x;
            read(pos), read(x);
            root[i] = modify(x,pos,root[i - 1]);

        }
        else {
            int t;
            read(t);
            root[i] = root[t];
        }
    }
}

18寒假第六測