将所有物品按照$b$的选择顺序排序,则先手在任意前$i$个物品中最多只能拿走$\lceil\frac{i}{2}\rceil$个物品。

将每个物品的价值设为$a+b$,那么答案为先手拿走的价值和减去所有物品的$b$之和,目标是最大化先手拿走的价值和。

如果不考虑修改,则满足拟阵,可以贪心选取,修改时最优解最多发生一处变动。

每个修改可以看作是先删除一个物品,再插入一个物品。

设$f[i]$表示$[1,i]$里选择的物品数减去$\lceil\frac{i}{2}\rceil$,则方案合法的条件为$\max(f[1,n])\leq 0$。

对于插入物品$x$:

  • 如果$x$可以直接加入最优解,那么直接加入。
  • 否则加入$x$会导致$f$中出现$1$,那么需要找到一个最优解中的价值最小的物品$y$,满足$y$在$f$从左往右第一个$1$之前,要么不选$x$,要么将$y$替换成$x$。

对于删除物品$x$:

  • 如果$x$不在最优解中,那么直接删除。
  • 否则删除$x$后可以继续多加入一个物品,那么需要找到一个不在最优解中的价值最大的物品$y$,满足$y$到$n$的所有$f$都是负数。

以上所有操作都可以用线段树维护,时间复杂度$O((n+m)\log n)$。

#include<cstdio>
#include<algorithm>
using namespace std;
typedef pair<int,int>P;
const int N=100010,M=262150,inf=~0U>>1,BUF=10000000;
char Buf[BUF],*buf=Buf;long long ans;
int n,m,i,x,y,pos[N];bool used[N];
P ma[M],mi[M];int f[M],tag[M];
struct E{int a,b,p;}e[N];
inline bool cmp(const E&a,const E&b){
if(a.b!=b.b)return a.b>b.b;
return a.p<b.p;
}
inline void read(int&a){for(a=0;*buf<48;buf++);while(*buf>47)a=a*10+*buf++-48;}
inline void up(int x){
ma[x]=max(ma[x<<1],ma[x<<1|1]);
mi[x]=min(mi[x<<1],mi[x<<1|1]);
}
void build(int x,int a,int b){
if(a==b){
ma[x]=P(-inf,a);
mi[x]=P(inf,a);
f[x]=-(a+1)/2;
return;
}
int mid=(a+b)>>1;
build(x<<1,a,mid),build(x<<1|1,mid+1,b),up(x);
f[x]=max(f[x<<1],f[x<<1|1]);
}
inline void tag1(int x,int p){f[x]+=p;tag[x]+=p;}
inline void pb(int x){if(tag[x])tag1(x<<1,tag[x]),tag1(x<<1|1,tag[x]),tag[x]=0;}
void maketag(int x,int a,int b,int c,int d,int p){
if(c<=a&&b<=d){tag1(x,p);return;}
pb(x);
int mid=(a+b)>>1;
if(c<=mid)maketag(x<<1,a,mid,c,d,p);
if(d>mid)maketag(x<<1|1,mid+1,b,c,d,p);
f[x]=max(f[x<<1],f[x<<1|1]);
}
void setused(int x,int a,int b,int c,int p){
if(a==b){
used[a]=1;
ma[x]=P(-inf,a);
mi[x]=P(p,a);
return;
}
int mid=(a+b)>>1;
if(c<=mid)setused(x<<1,a,mid,c,p);else setused(x<<1|1,mid+1,b,c,p);
up(x);
}
void setunused(int x,int a,int b,int c,int p){
if(a==b){
used[a]=0;
ma[x]=P(p,a);
mi[x]=P(inf,a);
return;
}
int mid=(a+b)>>1;
if(c<=mid)setunused(x<<1,a,mid,c,p);else setunused(x<<1|1,mid+1,b,c,p);
up(x);
}
int askf(int x,int a,int b,int c,int d){
if(c<=a&&b<=d)return f[x];
pb(x);
int mid=(a+b)>>1,t=-inf;
if(c<=mid)t=askf(x<<1,a,mid,c,d);
if(d>mid)t=max(t,askf(x<<1|1,mid+1,b,c,d));
return t;
}
P askmi(int x,int a,int b,int c,int d){
if(c<=a&&b<=d)return mi[x];
int mid=(a+b)>>1;P t(inf,0);
if(c<=mid)t=askmi(x<<1,a,mid,c,d);
if(d>mid)t=min(t,askmi(x<<1|1,mid+1,b,c,d));
return t;
}
P askma(int x,int a,int b,int c,int d){
if(c<=a&&b<=d)return ma[x];
int mid=(a+b)>>1;P t(-inf,0);
if(c<=mid)t=askma(x<<1,a,mid,c,d);
if(d>mid)t=max(t,askma(x<<1|1,mid+1,b,c,d));
return t;
}
inline int findfirstpos(){
int x=1,a=1,b=n,mid;
while(a<b){
pb(x);
mid=(a+b)>>1;
if(f[x<<1]>0)x=x<<1,b=mid;else x=x<<1|1,a=mid+1;
}
return a;
}
inline int findlastneg(){
int x=1,a=1,b=n,mid,ret=n+1;
while(a<b){
pb(x);
mid=(a+b)>>1;
if(f[x<<1|1]<0){
x=x<<1;
b=mid;
ret=mid+1;
}else{
x=x<<1|1;
a=mid+1;
}
}
if(f[x]<0)ret=a;
return ret;
}
inline void additem(int x){
int val=e[x].a+e[x].b,tmp=askf(1,1,n,x,n);
maketag(1,1,n,x,n,1);
if(tmp<0){
setused(1,1,n,x,val);
ans+=val;
return;
}
int o=findfirstpos();
maketag(1,1,n,x,n,-1);
P y=askmi(1,1,n,1,o);
if(y.first>=val){
setunused(1,1,n,x,val);
return;
}
ans+=val-y.first;
setunused(1,1,n,y.second,y.first);
maketag(1,1,n,y.second,n,-1);
setused(1,1,n,x,val);
maketag(1,1,n,x,n,1);
}
inline void delitem(int x){
if(!used[x])return;
ans-=e[x].a+e[x].b;
setunused(1,1,n,x,-inf);
maketag(1,1,n,x,n,-1);
int o=findlastneg();
if(o>n)return;
P y=askma(1,1,n,o,n);
if(y.first<=0)return;
ans+=y.first;
setused(1,1,n,y.second,y.first);
maketag(1,1,n,y.second,n,1);
}
int main(){
fread(Buf,1,BUF,stdin);read(n);
for(i=1;i<=n;i++)read(e[i].a);
for(i=1;i<=n;i++)read(e[i].b),e[i].p=i,ans-=e[i].b;
sort(e+1,e+n+1,cmp);
for(i=1;i<=n;i++)pos[e[i].p]=i;
build(1,1,n);
for(i=1;i<=n;i++)additem(i);
printf("%lld\n",ans);
read(m);
while(m--){
read(x),read(y);
x=pos[x];
delitem(x);
e[x].a=y;
additem(x);
printf("%lld\n",ans);
}
return 0;
}

  

BZOJ5326 : [Jsoi2017]博弈的更多相关文章

  1. BZOJ 5326 [JSOI2017]博弈 (模拟费用流、线段树)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=5326 题解 终于成为第8个A掉这题的人--orz tzw神仙早我6小时 本以为这东西常数 ...

  2. hdu----(1849)Rabbit and Grass(简单的尼姆博弈)

    Rabbit and Grass Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  3. HDU 5754 Life Winner Bo 组合博弈

    Life Winner Bo Problem Description   Bo is a "Life Winner".He likes playing chessboard gam ...

  4. HDU 2509 Nim博弈变形

    1.HDU 2509  2.题意:n堆苹果,两个人轮流,每次从一堆中取连续的多个,至少取一个,最后取光者败. 3.总结:Nim博弈的变形,还是不知道怎么分析,,,,看了大牛的博客. 传送门 首先给出结 ...

  5. HDU 1907 Nim博弈变形

    1.HDU 1907 2.题意:n堆糖,两人轮流,每次从任意一堆中至少取一个,最后取光者输. 3.总结:有点变形的Nim,还是不太明白,盗用一下学长的分析吧 传送门 分析:经典的Nim博弈的一点变形. ...

  6. 51nod1072(wythoff 博弈)

    题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1072 题意: 中文题诶~ 思路: 博弈套路是有的, 找np局 ...

  7. ACM: NBUT 1107 盒子游戏 - 简单博弈

     NBUT 1107  盒子游戏 Time Limit:1000MS     Memory Limit:65535KB     64bit IO Format:  Practice  Appoint ...

  8. 【转】ACM博弈知识汇总

    博弈知识汇总 转自:http://www.cnblogs.com/kuangbin/archive/2011/08/28/2156426.html 有一种很有意思的游戏,就是有物体若干堆,可以是火柴棍 ...

  9. Uva 10891 经典博弈区间DP

    经典博弈区间DP 题目链接:https://uva.onlinejudge.org/external/108/p10891.pdf 题意: 给定n个数字,A和B可以从这串数字的两端任意选数字,一次只能 ...

随机推荐

  1. JavaWeb处理GET、POST时的编码乱码问题

    对于GET方法,只要设置了res.setContentType("text/html;charset=UTF-8"), req.getParameter()就不会产生乱码. 对于P ...

  2. eclipse搭建elastic-job

    1.官网下载eclipse----面向Java EE企业级开发的Eclipse IDE for Java EE Developers:2.官网下载maven,并配置环境变量---MAVEN_HOME: ...

  3. Linux设置允许指定端口通过防火墙centos7

    开启防火墙 1.systemctl start firewalld.service(开启防火墙) 2.systemctl stop firewalld.service(开启防火墙) 3.service ...

  4. 最大K段和题解

    题目:XJOI335 传送门 [ >XJOI<] 重要提示:您的膜法等级必须达到3级6段才可使用本传送门,否则您会被小猫痛扁 因为博主太懒,不提供题面(QAQ)... 很容易想到使用DP, ...

  5. json中的json.dumps()

    Json简介 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于JavaScript(Standard ECMA-262 3rd Edition - ...

  6. 【interview】Microsoft面经

    ~~收集的面经~~ 1. 实现hashtable的put 和get操作 参考:https://yikun.github.io/2015/04/01/Java-HashMap%E5%B7%A5%E4%B ...

  7. Union 与 Union all 的区别【坑】

    UNION操作符用于合并两个或多个SELECT语句的结果集 请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列.列也必须拥有相似的数据类型.同时,每条 SELECT 语句中的列的顺序必 ...

  8. 洛谷P3307 [SDOI2013]项链 [polya定理,莫比乌斯反演]

    传送门 思路 很明显的一个思路:先搞出有多少种珠子,再求有多少种项链. 珠子 考虑这个式子: \[ S3=\sum_{i=1}^a \sum_{j=1}^a\sum_{k=1}^a [\gcd(i,j ...

  9. 详解MariaDB数据库的事务

    1.什么是事务 数据库事务:(database transaction): 事务是由一组SQL语句组成的逻辑处理单元,一组事务中的SQL语句要不全部执行成功功:如果其中某一条执行失败,则这组SQL语句 ...

  10. 《剑指offer》两个链表中的第一个公共节点

    本题来自<剑指offer> 反转链表 题目: 思路: C++ Code: Python Code: 总结: