2012 Asia Hangzhou/Jinhua Regional Contest

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;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值