hdu4453 Looploop
好题……虽然有一系列区间翻转区间求和等等平衡树才能玩得起的操作,但翻转的长度和增加的长度都是固定的。
而且题目中给了各种的条件,比如k1<k2≤N..就能有更简单的处理这些操作的办法。
开3个双端队列,第一个存指针后1~k1,第二个存k1+1~k2,第三个存剩下的数字。
那么对于区间翻转和区间求和,只需要修改两个deque的标记。
插入和删除也是只要修改第一个双端队列的头或尾,并且维护后两个队列满足要求
指针左右移也是纸上好好想想就能推出来了,略有些复杂。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cstdlib> #include <cmath> #include <cctype> #include <queue> #include <stack> #include <map> #include <set> #include <list> #define pb push_back #define mp make_pair #define fi first #define se second //#pragma comment(linker, "/STACK:16777216") using namespace std; typedef long long LL; typedef unsigned long long ULL; #define N 1000005 deque<int> Q1 , Q2 , Q3; int n , m , k1 , k2; int add , rev; void insert(int x) { int y; if (rev) y = Q1.back() , Q1.pop_back() , Q1.push_back(x - add) , Q1.push_back(y); else y = Q1.front() , Q1.pop_front() , Q1.push_front(x - add) , Q1.push_front(y); Q3.push_front(Q2.back() + add) , Q2.pop_back(); if (rev) Q2.push_front(Q1.front()) , Q1.pop_front(); else Q2.push_front(Q1.back()) , Q1.pop_back(); } void del() { int y; if (rev) Q1.pop_back() , Q1.push_front(Q2.front()) , Q2.pop_front() , Q2.push_back(Q3.front() - add) , Q3.pop_front(); else Q1.pop_front() , Q1.push_back(Q2.front()) , Q2.pop_front() , Q2.push_back(Q3.front() - add) , Q3.pop_front(); } int move(int x) { if (x == 1) { if (rev) { Q1.push_back(Q3.back() - add) , Q3.pop_back(); Q2.push_front(Q1.front()) , Q1.pop_front(); Q3.push_front(Q2.back() + add) , Q2.pop_back(); } else { Q1.push_front(Q3.back() - add) , Q3.pop_back(); Q2.push_front(Q1.back()) , Q1.pop_back(); Q3.push_front(Q2.back() + add) , Q2.pop_back(); } } else { if (rev) { Q3.push_back(Q1.back() + add) , Q1.pop_back(); Q2.push_back(Q3.front() - add) , Q3.pop_front(); Q1.push_front(Q2.front()) , Q2.pop_front(); } else { Q3.push_back(Q1.front() + add) , Q1.pop_front(); Q2.push_back(Q3.front() - add) , Q3.pop_front(); Q1.push_back(Q2.front()) , Q2.pop_front(); } } } void watch() { puts("*************"); for (deque<int>::iterator it = Q1.begin() ; it != Q1.end() ; ++ it) printf("%d " , *it + add); puts(""); for (deque<int>::iterator it = Q2.begin() ; it != Q2.end() ; ++ it) printf("%d " , *it + add); puts(""); for (deque<int>::iterator it = Q3.begin() ; it != Q3.end() ; ++ it) printf("%d " , *it); puts(""); puts("*************"); } int query() { if (rev) return Q1.back() + add; else return Q1.front() + add; } int ca; void work() { int i , j , x , y; char str[10]; while (!Q1.empty()) Q1.pop_back(); while (!Q2.empty()) Q2.pop_back(); while (!Q3.empty()) Q3.pop_back(); scanf("%d%d%d",&m,&k1,&k2); add = rev = 0; printf("Case #%d:\n" , ++ ca); for (i = 1 ; i <= n ; ++ i) { scanf("%d",&x); if (i <= k1) Q1.push_back(x); else if (i <= k2) Q2.push_back(x); else Q3.push_back(x); } //watch(); while (m --) { scanf("%s" , str); if (*str == 'i') scanf("%d",&x) , insert(x); if (*str == 'a') scanf("%d",&x) , add += x; if (*str == 'r') rev ^= 1; if (*str == 'd') del(); if (*str == 'm') scanf("%d",&x) , move(x); if (*str == 'q') printf("%d\n" , query()); //watch(); } } int main() { while (scanf("%d",&n) , n) work(); return 0; }
hdu4454 Stealing a Cake
三分
hdu4455 Substrings
好题
hdu4456 Crowd
10000*10000的矩阵,单点增加,询问一个菱形的权值和。
菱形只要转一下就好了(x+y,x-y)在一定的范围内就是一个矩形。
就成了一个20000*20000的矩阵,单点增加,询问一个子矩阵的权值和……
原来想的是树状数组,给id套一个Hash,但是HDU内存有些紧,MLE无解。
没办法就用树套树了,用树状数组维护前缀套一个Treap,Treap询问区间和
空间复杂度就是O(mlogn)了。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cstdlib> #include <cmath> #include <cctype> #include <queue> #include <stack> #include <map> #include <set> #include <list> #define pb push_back #define mp make_pair #define fi first #define se second //#pragma comment(linker, "/STACK:16777216") using namespace std; typedef long long LL; typedef unsigned long long ULL; #define N 1200005 #define M 20005 int n , m , root[M]; struct Treap { int priority[N] , child[N][2]; pair<int , int> key[N] ; int sum[N]; int Size[N] , cnt[N] , nodecnt; Treap() { priority[0] = 0x7FFFFFFF; } void clear() { nodecnt = 1; Size[0] = cnt[0] = sum[0] = 0 , key[0] = make_pair(0 , 0); } int size(int x) { return Size[root[x]]; } void update(int x) { Size[x] = Size[child[x][0]] + Size[child[x][1]] + cnt[x]; sum[x] = sum[child[x][0]] + sum[child[x][1]] + key[x].second * cnt[x]; } void rotate (int& x , int t) { int y = child[x][t]; child[x][t] = child[y][t ^ 1]; child[y][t ^ 1] = x; update(x) , update(y); x = y; } void insert(int& x , pair<int , int> k) { if (x) { if (key[x] == k) ++ cnt[x]; else { int t = key[x] < k; insert(child[x][t] , k); if (priority[child[x][t]] < priority[x]) rotate(x , t); } } else { x = nodecnt ++; key[x] = k; sum[x] = k.second; cnt[x] = 1; priority[x] = rand() << 15 | rand(); child[x][0] = child[x][1] = 0; } update(x); } void query(int x , int l , int r , int& ans) { if(!x) return; int val = key[x].first; if( l <= val && val <= r) { ans += key[x].second * cnt[x]; if(l == -1 << 30) { ans += sum[child[x][0]]; query(child[x][1] , l , r, ans); } else if(r == 1 << 30) { query(child[x][0] , l, r, ans); ans += sum[child[x][1]]; } else { query(child[x][0] , l , 1 << 30 , ans); query(child[x][1] , -1 << 30, r , ans); } return; } if(r < val) query(child[x][0] , l, r, ans); if(val < l) query(child[x][1] , l, r, ans); } }; Treap T; void add(int x , int y , int w) { for (int i = x ; i < n + n ; i += i & -i) T.insert(root[i] , make_pair(y , w)); } int query(int x , int y , int z) { int res = 0 , val; for (int i = x ; i > 0 ; i -= i & -i) val = 0 , T.query(root[i] , y , z , val) , res += val; return res; } void work() { int i , j , x , y , z , p , q; memset(root , 0 , sizeof(root)); T.clear(); scanf("%d",&m); /*for (i = 300000 ; ; -- i) { for (j = 2 ; j * j <= i ; ++ j) if (i % j == 0) break; if (j * j > i) break; }cout <<i << endl;*/ while (m --) { scanf("%d%d%d%d",&i,&p,&q,&z); if (i == 1) { x = p + q - 1; y = p - q + n; add(x , y , z); } else { x = p + q - 1; y = p - q + n; i = x - z , j = y - z , x += z , y += z; i = max(1 , i) , j = max(1 , j); x = min(n + n - 1 , x) , y = min(n + n - 1 , y); printf("%d\n" , query(x , j , y) - query(i - 1 , j , y)); } } } int main() { while (scanf("%d",&n) , n) //int _ ; scanf("%d",&_); while(_--) work(); return 0; }
杭州剩下会做的就只有后面四道简单题了。。
金华
hdu4445 Crazy Tank
求出所有存在炮弹落在L1或L2的角度,然后挨个判定就没问题了。
但是这个角度好像不好求。。。
那就挨个枚举角度吧……
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cstdlib> #include <cmath> #include <cctype> #include <queue> #include <stack> #include <map> #include <set> #include <list> #define pb push_back #define mp make_pair #define fi first #define se second //#pragma comment(linker, "/STACK:16777216") using namespace std; typedef long long LL; typedef unsigned long long ULL; #define N 1005 #define M 20005 int n; double l1 , l2 , r1 , r2 , v[N] , h , pi = acos(-1.) , alpha , g = 9.8; int cal() { int sum = 0 , i ; for (i = 0 ; i < n ; ++ i) { double vx = sin(alpha) * v[i] , vy = cos(alpha) * v[i]; double det = vy * vy + 2 * g * h , t = (-vy + sqrt(det)) / g , x = t * vx; if (x >= l1 && x <= r1) ++ sum; if (x >= l2 && x <= r2) return 0; } return sum; } void work() { int i , ans = 0; scanf("%lf%lf%lf%lf%lf",&h,&l1,&r1,&l2,&r2); for (i = 0 ; i < n ; ++ i) scanf("%lf",&v[i]); double eps = pi / 500.0; for (alpha = 0 ; alpha - 1e-9 <= pi ; alpha += eps) { ans = max(ans , cal()); if (ans == n )break; } printf("%d\n" , ans); } int main() { while (scanf("%d",&n) , n) //int _ ; scanf("%d",&_); while(_--) work(); return 0; }
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cstdlib> #include <cmath> #include <cctype> #include <queue> #include <stack> #include <utility> #include <map> #define pb push_back #define mp make_pair #define N 1205 using namespace std; typedef long long ll; struct poly { int drg , a[N]; }; poly p[N]; poly operator / (poly x , poly y) { poly ans = {}; ans.drg = x.drg - y.drg; for (int i = x.drg ;i >= y.drg ; -- i) if (x.a[i]) { ans.a[i - y.drg] = x.a[i] / y.a[y.drg]; for (int j = 0 ;j <= y.drg ; ++ j) x.a[i - y.drg + j] -= ans.a[i - y.drg] * y.a[j]; } while (ans.drg > 1 && !ans.a[ans.drg]) -- ans.drg; return ans; } bool cmp(int x , int y) { if (p[x].drg == p[y].drg) for (int i = p[x].drg ; i >= 0 ; -- i) if (abs(p[x].a[i]) == abs(p[y].a[i])) { if (p[x].a[i] != p[y].a[i]) return (p[x].a[i] < p[y].a[i]); } else return abs(p[x].a[i]) < abs(p[y].a[i]); return p[x].drg < p[y].drg; } void print(poly x) { printf("("); for (int i = x.drg ; i >= 1 ; i --) if (x.a[i]) { if (x.a[i] < 0) putchar('-'); else if (i != x.drg) putchar('+'); if (abs(x.a[i]) != 1) printf("%d",abs(x.a[i])); putchar('x'); if (i > 1) printf("^%d",i); } if (x.a[0] > 0) printf("+%d",x.a[0]); if (x.a[0] < 0) printf("%d",x.a[0]); printf(")"); } void init() { int i , j; for (i = 1 ; i <= 1200; i ++) { p[i].drg = i , p[i].a[0] = -1 , p[i].a[i] = 1; for (j = 1 ; j < i ;j ++) if (i % j == 0) p[i] = p[i] / p[j]; } } int n ; void work() { vector<int> ans; if (n == 1) { puts("x-1"); return; } for (int i = 1 ; i <= n ; i ++) if (n % i == 0) ans.pb(i); sort(ans.begin() , ans.end() , cmp); for (int i = 0 ;i < int(ans.size()); ++ i) print(p[ans[i]]); printf("\n"); } int main() { init(); while (cin >> n , n) work(); return 0; }