[非旋转Treap 权值线段树] 2016 计蒜之道 初赛 第五场 腾讯的新游戏

可以发现对于每个队伍 最小需要的防御值是max(ai-i+1)

因为打到第i个时已经加了i-1防御 

然后所有队伍从小到大排序后 答案求法亦然

那么我用treap维护每个队列 

用权值线段树维护答案


#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;

inline char nc(){
  static char buf[100000],*p1=buf,*p2=buf;
  if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
  return *p1++;
}

inline void read(int &x){
  char c=nc(),b=1;
  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') c=nc();
  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int N=100005;

struct node{
  node *l,*r;
  int size;
  int val,tag,maxv;
  void updata(){
    maxv=val; size=1;
    if (l!=NULL) maxv=max(maxv,l->maxv),size+=l->size;
    if (r!=NULL) maxv=max(maxv,r->maxv),size+=r->size;
  }
  void mark(int t){
    tag+=t,val+=t,maxv+=t;
  }
  void Pushdown(){
    if (l!=NULL) l->mark(tag);
    if (r!=NULL) r->mark(tag);
    tag=0;
  }
}nodes[N<<2];
int ncnt=0;

inline node* Build(int l,int r,int *a){
  if (l>r) return NULL;
  int mid=(l+r)>>1;
  node *tmp=nodes+(++ncnt);
  tmp->size=1; tmp->maxv=tmp->val=a[mid]-mid+1; tmp->tag=0;
  tmp->l=Build(l,mid-1,a);
  tmp->r=Build(mid+1,r,a);
  tmp->updata();
  return tmp;
}

typedef pair<node*,node*> Droot;

inline int ran(){
  static int x=31253125; x+=(x<<4)+1; return x&65536;
}

inline node* M(node *x,node *y){
  if (!x || !y) return x?x:y;
  x->Pushdown(); y->Pushdown();
  if (ran()){
    y->l=M(x,y->l); y->updata();
    return y;
  }else{
    x->r=M(x->r,y); x->updata();
    return x;
  }
}
inline int Size(node *x){
  return x?x->size:0;
}
inline Droot S(node *x,int k){
  if(!x) return Droot(NULL,NULL);
  x->Pushdown(); Droot y;
  if(Size(x->l)>=k){
    y=S(x->l,k);
    x->l=y.second; x->updata();
    y.second=x;
  }else{
    y=S(x->r,k-Size(x->l)-1);
    x->r=y.first; x->updata();
    y.first=x;
  }
  return y;
}

int n,Q;
int a[N];
int tot[N];
node *head[N];

struct SEG{
  int T[N<<2],F[N<<2]; int C[N];
  int n,M,TH;
  inline void Build(int _n){
    n=_n;
    for (M=1;M<n+2;M<<=1,TH++);
  }
  inline void Pushdown(int rt){
    for (int i=TH,p;i;i--)
      if (F[p=rt>>i]){
	T[p<<1]+=F[p]; F[p<<1]+=F[p];
	T[p<<1|1]+=F[p]; F[p<<1|1]+=F[p];
	F[p]=0;
      }
  }
  inline void Add(int s,int t,int r){
    for (Pushdown(s+=M-1),Pushdown(t+=M+1);s^t^1;){
      if (~s&1) T[s^1]+=r,F[s^1]+=r;
      if ( t&1) T[t^1]+=r,F[t^1]+=r;
      T[s>>=1]=max(T[s<<1],T[s<<1|1]);
      T[t>>=1]=max(T[t<<1],T[t<<1|1]);
    }
    while (s>>=1)
      T[s]=max(T[s<<1],T[s<<1|1]);
  }
  inline int Query(){
    return T[1];
  }
  inline void Change(int val,int num,int r){
    if (r==1){
      if (C[val]==0)
	Add(val,val,val);
      C[val]++;
      Add(val+1,n,-num);
    }else{
      if (C[val]==1)
	Add(val,val,-val);
      C[val]--;
      Add(val+1,n,num);
    }
  }
}Seg;


inline void Solve(int x,int a,int y,int b){
  if (head[x]) Seg.Change(head[x]->maxv,head[x]->size,-1);
  if (head[y]) Seg.Change(head[y]->maxv,head[y]->size,-1);
  Droot A=S(head[x],a),B=S(head[y],b);
  if (A.second) A.second->mark(Size(A.first)-Size(B.first));
  if (B.second) B.second->mark(Size(B.first)-Size(A.first));
  head[x]=M(B.first,A.second);
  head[y]=M(A.first,B.second);
  if (head[x]) Seg.Change(head[x]->maxv,head[x]->size,1);
  if (head[y]) Seg.Change(head[y]->maxv,head[y]->size,1);
}


int main(){
  int in; int ix,ia,iy,ib;
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  read(n);
  Seg.Build(100000);
  for (int i=1;i<=n;i++){
    read(tot[i]);
    for (int j=1;j<=tot[i];j++) read(a[j]);
    head[i]=Build(1,tot[i],a);
    if (head[i]) Seg.Change(head[i]->maxv,head[i]->size,1);
  }
  read(Q);
  while (Q--){
    read(ix); read(ia); read(iy); read(ib);
    Solve(ix,ia,iy,ib);
    printf("%d\n",Seg.Query());
  }
  return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是Treap的代码: ``` #include <bits/stdc++.h> using namespace std; struct Node { int key, priority; Node *left, *right; Node(int key, int priority) : key(key), priority(priority), left(NULL), right(NULL) {} }; struct Treap { Node *root; Treap() : root(NULL) {} void rotateRight(Node *&p) { Node *q = p->left; p->left = q->right; q->right = p; p = q; } void rotateLeft(Node *&p) { Node *q = p->right; p->right = q->left; q->left = p; p = q; } void insert(Node *&p, int key, int priority) { if (p == NULL) { p = new Node(key, priority); return; } if (key < p->key) { insert(p->left, key, priority); if (p->priority < p->left->priority) { rotateRight(p); } } else { insert(p->right, key, priority); if (p->priority < p->right->priority) { rotateLeft(p); } } } void remove(Node *&p, int key) { if (p == NULL) { return; } if (key == p->key) { if (p->left == NULL || p->right == NULL) { Node *q = p; if (p->left == NULL) { p = p->right; } else { p = p->left; } delete q; } else { if (p->left->priority > p->right->priority) { rotateRight(p); remove(p->right, key); } else { rotateLeft(p); remove(p->left, key); } } } else if (key < p->key) { remove(p->left, key); } else { remove(p->right, key); } } bool search(Node *p, int key) { if (p == NULL) { return false; } if (key == p->key) { return true; } if (key < p->key) { return search(p->left, key); } else { return search(p->right, key); } } }; int main() { Treap t; t.insert(t.root, 5, rand()); t.insert(t.root, 3, rand()); t.insert(t.root, 8, rand()); t.insert(t.root, 1, rand()); t.insert(t.root, 4, rand()); t.insert(t.root, 6, rand()); t.insert(t.root, 9, rand());

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值