hdu4027 剪枝+用不上懶標記的線段樹
阿新 • • 發佈:2018-12-11
給n個數
然後兩種操作
0操作 把【l,r】的數都開根(向下取整)
1操作 輸出【l,r】的區間和
因為這是每個數開根 而不是加上 所以結點沒法直接更新
不同於懶標記 懶標記是把當前結點標記了,同時也更新當前結點的資訊 然後直接返回
注意懶標記下面的資料還沒更新的!! 但是沒關係 如果下次訪問到 pushdown會幫我們把上面的懶標記傳下去
從而更新 這就是所謂的“懶” 用到時才行動 所以高效
這題解決:全都走到葉節點加
直接更新葉節點 然後靠pushup把上面修正
然而TLE
還需要一個剪枝 我們知道開根 2^63
開一次2^31 2^15 2^7 2^3 2^1 2^0
也就那麼6 、7 次
1開根還是1 就沒必要再去開根了
秒: 如果區間和 比如【2,7】的區間和 若是7-2+1=6 這裡面就有6個數 這說明 從rt開始 葉節點都是1 那既然是1 就不用再下去 開根還是1
如 1--3 3
1--2 3 對應的值 2 1
1 2 1 1
所以直接返回 當前結點的這一子樹 無需做無用功
#include<iostream> #include<cstring> #include<cmath> #include<string> #include<map> #include<vector> #include<set> #include<queue> #include<cstdio> #include<cstdlib> #include<algorithm> #include<functional> using namespace std; #define inf 0x3f3f3f3f #define pi acos(-1.0) #define LL long long #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 //#define mp make_pair #define pb push_back #define ULL unsigned LL #define mem(a, b) memset(a, b, sizeof(a)) #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) //#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout); const int maxn = 1e5 + 100; LL sum[4 * maxn]; //int lazy[4* maxn]; inline void pushup(int rt){ sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; } void build(int l, int r, int rt){ if (l == r){ scanf("%lld", &sum[rt]); return; } int m = l + (r - l) / 2; build(lson); build(rson); pushup(rt); } void update(int L, int R, int l, int r, int rt){ //因為這是每個數開根 而不是加上 所以結點沒法直接更新 //解決:全都走到葉節點加 //直接更新葉節點 然後考pushup把上面修正 if (l == r){ sum[rt] = sqrt(sum[rt] * 1.0);//轉成long long 相當於向下取整 return; } //如果區間和 比如【2,7】的區間和 若是7-2+1=6 這裡面就有6個數 //這說明 從rt開始 葉節點都是1 那既然是1 就不用再下去 開根還是1 if (L <= l && R >= r && sum[rt] == r - l + 1) return; int m = l + (r - l ) / 2; //pushdown(rt, m - l + 1, r - m); if (m >= L) update(L, R, lson); if (m + 1<= R) update(L, R, rson); pushup(rt); } LL query(int L, int R, int l, int r, int rt){ if (l >= L && r <= R){ return sum[rt]; } LL res = 0; int m = l + (r - l ) / 2; if (m >= L) res += query(L, R, lson); if (m + 1 <= R) res += query(L, R, rson); return res; } int main(){ int n; int cas = 1; while (~scanf("%d", &n)){ mem(sum, 0); printf("Case #%d:\n", cas++); build(1, n, 1); int m; scanf("%d", &m); int a, b, c; while (m--){ scanf("%d%d%d", &a, &b, &c); int f = min(b, c), s = max(b, c); if (a == 0) update(f, s, 1, n, 1); else if (a == 1) printf("%lld\n", query(f, s, 1, n, 1)); } puts(""); } return 0; }