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;
}
hdu4447 Yuanfang, What Do You Think?
#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;
}