标签:style blog http color io os ar for sp
题目链接 :http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5332
比赛的时候没有做出来,赛后看了官方题解,虽然各种orz但是依旧只能orz(标程写得真是犀利),然后可耻的到网上找了下题解。。。
做法是线段树 + 离线搞, 网上那种对于[l, r]中的l从大到小排序很精妙(有一篇竟然说是以r为关键字,,,然后代码里面却是l。。。汗), 再注意到gcd()对于每一个起点来说,是单调递减的,这样可以乱搞了...
如果还不是很明白,搜下其他的blog吧,他们写得很丰富。。
贴贴代码,,可耻滚粗。
ps .... zoj为何有时能过有时候又被卡了。。。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <vector> 5 //#include <cmath> 6 7 using namespace std; 8 #define lson rt<<1, l, mid 9 #define rson rt<<1|1, mid+1, r 10 typedef pair<int, int> PII; 11 //typedef __int64 lld; 12 typedef long long lld; 13 const int MAXN = 100005; 14 15 struct Q { 16 int l, r, id; 17 Q() {} 18 Q(int a, int b, int c):l(a), r(b), id(c) {} 19 bool operator < (const Q& cmp) const { 20 return l > cmp.l; 21 } 22 }; 23 vector<Q> GS[55]; 24 int a[MAXN]; 25 lld sum[MAXN << 2]; 26 lld add[MAXN << 2]; 27 int n, m, q; 28 lld out[MAXN]; 29 int log2[MAXN]; 30 31 struct RMQ { 32 int a[MAXN][22]; 33 void init(int A[], int N) { 34 for (int i = 1; i <= N; i++) a[i][0] = A[i]; 35 for (int j = 1; (1 << j) <= N; j++) { 36 for (int i = 1; i + j - 1 <= N; i++) { 37 a[i][j] = __gcd(a[i][j-1], a[i + (1<<(j-1))][j - 1]); 38 } 39 } 40 } 41 int rmq(int L, int R) { 42 // if (R < L) while (1); 43 if (R < L) return 0; 44 int k = log2[R - L + 1]; 45 return __gcd(a[L][k], a[R-(1<<k)+1][k]); 46 } 47 }AC; 48 49 /* *segment tree* */ 50 void build() { 51 memset(add, 0, sizeof(add)); 52 memset(sum, 0, sizeof(sum)); 53 } 54 void Down(int rt, int l, int r) { 55 if (add[rt]) { 56 int mid = r + l >> 1; 57 add[rt<<1] += add[rt]; 58 add[rt<<1|1] += add[rt]; 59 sum[rt<<1] += (lld)(mid - l + 1) * add[rt]; 60 sum[rt<<1|1] += (lld)(r - mid) * add[rt]; 61 add[rt] = 0; 62 } 63 return ; 64 } 65 void Up(int rt) { 66 sum[rt] = sum[rt<<1] + sum[rt<<1|1]; 67 } 68 void update(int rt, int l, int r, int L, int R) { 69 if (L > R) return ; 70 if (l >= L && r <= R) { 71 add[rt] += 1; 72 sum[rt] += r - l + 1; 73 return ; 74 } 75 Down(rt, l, r); 76 int mid = r + l >> 1; 77 if (mid >= L) update(lson, L, R); 78 if (R > mid) update(rson, L, R); 79 Up(rt); 80 } 81 lld query(int rt, int l, int r, int L, int R) { 82 if (L > R) return 0LL; 83 if (l >= L && r <= R) { 84 return sum[rt]; 85 } 86 Down(rt, l, r); 87 int mid = r + l >> 1; 88 lld ret = 0; 89 if (mid >= L) ret += query(lson, L, R); 90 if (R > mid) ret += query(rson, L, R); 91 return ret; 92 } 93 /* *segment tree* */ 94 95 PII arr[MAXN]; 96 void solve(vector<Q> vec, int M) { 97 sort(vec.begin(), vec.end()); 98 build(); 99 int l = 1, r = 1; 100 for (int i = 1; i <= n; i++) { 101 if (a[i] % M != 0 || AC.rmq(i, n) % M == 0 && AC.rmq(i, n) > M) { 102 arr[i] = make_pair(-1, -1); 103 }else { 104 l = max(l, i); //r = max(r, i); 105 while (l <= n && AC.rmq(i, l) % M == 0 && AC.rmq(i, l) > M) ++ l; 106 r = max(l, r); 107 while (r+1 <= n && AC.rmq(i, r+1) == M) ++ r; 108 if (AC.rmq(i, l) == M) { 109 arr[i] = make_pair(l, r); 110 }else { 111 arr[i] = make_pair(-1, -1); 112 } 113 } 114 } 115 int now = n, siz = vec.size(); 116 for (int i = 0; i < siz; i++) { 117 Q e = vec[i]; 118 while (now >= 1 && e.l <= now) { 119 if (arr[now].first != -1) { 120 update(1, 1, n, max(1, arr[now].first), arr[now].second); 121 } 122 -- now; 123 } 124 out[e.id] = query(1, 1, n, e.l, e.r); 125 } 126 } 127 /* 128 129 4 4 4 130 1 2 3 4 131 1 2 3 4 132 0 4 1 133 0 4 2 134 0 4 3 135 0 4 4 136 137 4 4 4 138 1 2 3 4 139 1 2 3 4 140 0 4 1 141 0 4 2 142 0 2 1 143 3 4 4 144 145 */ 146 147 int gs[55]; 148 int main() { 149 for (int i = 0; i < MAXN; i++) { 150 log2[i] = (i == 0 ? -1 : log2[i >> 1] + 1); 151 } 152 while (scanf("%d%d%d", &n, &m, &q) == 3) { 153 for (int i = 1; i <= n; i++) scanf("%d", &a[i]); 154 AC.init(a, n); 155 for (int i = 0; i < m; i++) scanf("%d", &gs[i]); 156 sort(gs, gs + m); 157 for (int i = 0; i < m; i++) GS[i].clear(); 158 for (int i = 1; i <= q; i++) { 159 int l, r, x; 160 scanf("%d%d%d", &l, &r, &x); 161 x = lower_bound(gs, gs + m, x) - gs; 162 GS[x].push_back(Q(l + 1, r, i)); 163 } 164 for (int i = 0; i < m; i++) { 165 solve(GS[i], gs[i]); 166 } 167 for (int i = 1; i <= q; i++) printf("%lld\n", out[i]); 168 } 169 return 0; 170 }
ZOJ 5332 Calculation(离线 + 线段树)
标签:style blog http color io os ar for sp
原文地址:http://www.cnblogs.com/danceonly/p/4004749.html