【HMOI】小C的填数游戏 DP+线段树维护
【题目描述】
一个长为n的序列,每个元素有一个a[i],b[i],a[i]为0||1,每个点和他相邻的两个点分别有两条边,权值为cost1[i],cost2[i],对于每个区间l,r,我们可以给每一个数一个c[i]值,c[i]=0||1,使得Σ(b[j]*(a[j]^c[j]))+cost1[j]*(c[j]^c[j+1])+cost2[j]*(c[j]^c[j+2]),j,j+1,j+2在[l,r]内时累加,现在有m次操作:
M x:将x位置的a[i]^=1;
Q l r:询问区间l,r的答案。
首先假设询问的只是一个区间,那么我们可以比较容易的用dp来求解w[i][s]表示到第i位的时候,后两位选的s的最小值,那么我们可以转移到w[i+1][ss]。这样就可以得到答案了。
但是现在我们支持区间询问和修改,所以我们用线段树来维护,每个节点记录w[s],s为这个区间左面两个点c[i]的选取方法和右面两个点的选取方法,那么只要我们可以维护线段树每个节点的w[i],我们就可以解决这个问题了。
对于合并操作比较简单,只需要枚举两个节点的s,然后更新的ss就可以了。
反思:一个节点的情况需要特殊处理,开始没注意到这个,后来改了半天,合并的时候还分了三种情况讨论= =。
还需要开LL,设inf的时候设的是#define inf (1<<60) 结果改了半天= =
评测数据的5号评测点少了一个操作,然后我的输出就多了一行= =。
//By BLADEVIL
#include <cstdio>
#include <cstring>
#define min(x,y) (x>y)?y:x;
#define inf (1ll<<60)
#define maxn 30010
#define LL long long using namespace std; struct rec {
int left,right;
LL key;
LL w[];
rec() {
left=right=;
key=inf;
for (LL i=;i<;i++) w[i]=inf;
}
}t[maxn<<]; LL n,m;
LL a[maxn],b[maxn],cost1[maxn],cost2[maxn];
char s[]; void init(int x) {
t[x].w[]=b[t[x].left]*a[t[x].left];
t[x].w[]=b[t[x].left]*(a[t[x].left]^);
t[x].key=min(t[x].w[],t[x].w[]);
} rec update(rec a,rec b) {
rec ans;
ans.left=a.left; ans.right=b.right;
if ((a.left==a.right)&&(b.left==b.right))
for (LL s=;s<;s++) {
LL ss=s|(s<<);
LL c1=((s&)==)?:,c2=((s&)==)?:;
//if ((ss==3)&&(a.left==1)) printf("%d %d\n",c1,c2);
if ((a.w[c1]==inf)||(b.w[c2]==inf)) continue;
ans.w[ss]=min(ans.w[ss],a.w[c1]+b.w[c2]+(c1^c2)*cost1[a.right]);
//if ((ss==3)&&(a.left==1)&&(a.right==1)) printf("%d\n",ans.w[ss]);
ans.key=min(ans.key,ans.w[ss]);
//if ((a.left==1)&&(a.right==1)) printf("%d %d\n",ans.key,ss);
} else
if (a.left==a.right)
for (LL s1=;s1<;s1++)
for (LL s2=;s2<;s2++) {
if ((a.w[s1]==inf)||(b.w[s2]==inf)) continue;
LL s=;
s|=s1<<; s|=(s2&)>>; s|=s2&;
LL c2=((s2&)==)?:,c3=((s2&)==)?:;
ans.w[s]=min(ans.w[s],a.w[s1]+b.w[s2]+(s1^c2)*cost1[a.left]+(s1^c3)*cost2[a.left]);
ans.key=min(ans.key,ans.w[s]);
} else
if (b.left==b.right)
for (LL s1=;s1<;s1++)
for (LL s2=;s2<;s2++) {
if ((a.w[s1]==inf)||(b.w[s2]==inf)) continue;
LL s=;
s|=s2; s|=(s1&)<<; s|=s1&;
LL c1=((s1&)==)?:,c2=((s1&)==)?:;
ans.w[s]=min(ans.w[s],a.w[s1]+b.w[s2]+(c1^s2)*cost2[a.right-]+(c2^s2)*cost1[a.right]);
ans.key=min(ans.key,ans.w[s]);
} else
if ((a.left!=a.right)&&(b.left!=b.right))
for (LL s1=;s1<;s1++)
for (LL s2=;s2<;s2++) {
if ((a.w[s1]==inf)||(b.w[s2])==inf) continue;
LL s=(s1>>)<<;
s|=s2&;
LL c1=((s1&)==)?:,c2=((s1&)==)?:;
LL c3=((s2&)==)?:,c4=((s2&)==)?:;
LL Ans=a.w[s1]+b.w[s2];
Ans+=cost1[a.right]*(c2^c3)+cost2[a.right]*(c2^c4)+cost2[a.right-]*(c1^c3);
ans.w[s]=min(ans.w[s],Ans);
ans.key=min(ans.key,ans.w[s]);
}
return ans;
} void build(int x,int l,int r) {
t[x].left=l; t[x].right=r;
if (t[x].left==t[x].right) {
init(x);
return ;
}
int mid=l+r>>;
build(x<<,l,mid); build((x<<)+,mid+,r);
t[x]=update(t[x<<],t[(x<<)+]);
} rec query(int x,int l,int r) {
if ((t[x].left==l)&&(t[x].right==r)) return t[x];
int mid=t[x].left+t[x].right>>;
if (mid>=r) return query(x<<,l,r); else
if (mid<l) return query((x<<)+,l,r); else
return update(query(x<<,l,mid),query((x<<)+,mid+,r));
} void change(int x,int y) {
if (t[x].left==t[x].right) {
init(x);
return ;
}
LL mid=t[x].left+t[x].right>>;
if (y>mid) change((x<<)+,y); else change(x<<,y);
t[x]=update(t[x<<],t[(x<<)+]);
} int main() {
freopen("game.in","r",stdin); freopen("game.out","w",stdout);
scanf("%lld%lld",&n,&m);
for (LL i=;i<=n;i++) scanf("%lld",&a[i]);
for (LL i=;i<=n;i++) scanf("%lld",&b[i]);
for (LL i=;i<n;i++) scanf("%lld",&cost1[i]);
for (LL i=;i<n-;i++) scanf("%lld",&cost2[i]);
build(,,n);
/*
for (LL s=0;s<16;s++) printf("%d %d\n",s,query(1,1,3).w[s]);
return 0;
*/
//printf("%d\n",query(1,2,4).key); return 0;
while (m--) {
scanf("%s",s);
LL x,y;
if (s[]=='Q') {
scanf("%lld%lld",&x,&y);
printf("%lld\n",query(,x,y).key);
} else {
scanf("%lld",&x);
a[x]^=;
change(,x);
}
}
//for (LL s=0;s<16;s++) printf("%d %d\n",s,query(1,1,4).w[s]);
fclose(stdin); fclose(stdout);
return ;
}
【HMOI】小C的填数游戏 DP+线段树维护的更多相关文章
- 小C的填数游戏
题意: 给出一张n个点的无向图 i连向i-1和i-2 边权为wij 有两个点权ai和bi ai为0或1 在给m个操作 1.将ai异或1 2.将区间x到y的点都填上一个数ci 使得Σ(bi*(ai^ci ...
- Codeforces 834D The Bakery【dp+线段树维护+lazy】
D. The Bakery time limit per test:2.5 seconds memory limit per test:256 megabytes input:standard inp ...
- [动态dp]线段树维护转移矩阵
背景:czy上课讲了新知识,从未见到过,总结一下. 所谓动态dp,是在动态规划的基础上,需要维护一些修改操作的算法. 这类题目分为如下三个步骤:(都是对于常系数齐次递推问题) 1先不考虑修改,不考虑区 ...
- Subsequence Count 2017ccpc网络赛 1006 dp+线段树维护矩阵
Problem Description Given a binary string S[1,...,N] (i.e. a sequence of 0's and 1's), and Q queries ...
- bzoj 1594: [Usaco2008 Jan]猜数游戏——二分+线段树
Description 为了提高自己低得可怜的智商,奶牛们设计了一个新的猜数游戏,来锻炼她们的逻辑推理能力. 游戏开始前,一头指定的奶牛会在牛棚后面摆N(1 <= N<= 1,000,00 ...
- 【bzoj1594-猜数游戏】线段树
题解: 矛盾只有两种情况: 一.先前确定了x在区间(l,r),但是现在发现x在区间(l1,r1),并且两个区间不相交. 二.一个区间的最小值是x,这个区间中有一个子区间的最小值比x更小. 首先可以明确 ...
- DP+线段树维护矩阵(2019牛客暑期多校训练营(第二场))--MAZE
题意:https://ac.nowcoder.com/acm/contest/882/E 给你01矩阵,有两种操作:1是把一个位置0变1.1变0,2是问你从第一行i开始,到最后一行j有几种走法.你只能 ...
- Codeforces 833B 题解(DP+线段树)
题面 传送门:http://codeforces.com/problemset/problem/833/B B. The Bakery time limit per test2.5 seconds m ...
- @NOIP2018 - D2T2@ 填数游戏
目录 @题目描述@ @题解@ @代码@ @题目描述@ 小 D 特别喜欢玩游戏.这一天,他在玩一款填数游戏. 这个填数游戏的棋盘是一个 n×m 的矩形表格.玩家需要在表格的每个格子中填入一个数字(数字 ...
随机推荐
- 网上的腾讯php面试题 (有答案版本)
一.PHP开发部分1.合并两个数组有几种方式,试比较它们的异同 答:1.array_merge()2.’+’3.array_merge_recursive array_merge 简单的合并数组arr ...
- Gradle sync failed: Failed to find Build Tools revision 26.0.2的解决办法
说明在android studio中没有 build tools 的26.0.2的版本,你确认一下,是否是这样: 点击==>android studio的菜单栏中Tools==>andro ...
- WASM
WASM WebAssembly https://webassembly.org/ https://github.com/appcypher/awesome-wasm-langs https://me ...
- overflow:scroll 滚动条不显示
overflow:scroll 滚动条不显示 ::-webkit-scrollbar-thumb 可能因为 自定义的滚动条height比元素可展示内容大
- RT-thread内核之IO设备管理系统
RT-Thread系统的IO设备管理模块为上层应用提供了一个对设备进行访问的通用抽象接口,而对于下层设备来说则提供了底层设备驱动框架,并通过定义的数据结构对设备信息和底层设备驱动进行管理.从系统整体位 ...
- iOS-开发中的时间处理
做App避免不了要和时间打交道,关于时间的处理,里面有不少门道,远不是一行API调用,获取当前系统时间这么简单.我们需要了解与时间相关的各种API之间的差别,再因场景而异去设计相应的机制. 时间的形式 ...
- Python 断言和异常
Python 断言和异常 Python断言 断言是一种理智检查,当程序的测试完成,可以将其打开或关闭.断言的最简单方法就是把它比作raise-if语句(或更加准确,raise-if-not声明).一个 ...
- COGS 705——回家
描述 USACO 2.4.4 现在是晚餐时间,而母牛们在外面分散的牧场中. 农民约翰按响了电铃,所以她们开始向谷仓走去. 你的工作是要指出哪只母牛会最先到达谷仓(在给出的测试数据中,总会有且只有一只最 ...
- P4316 绿豆蛙的归宿
题意翻译 「Poetize3」 题目背景 随着新版百度空间的上线,Blog宠物绿豆蛙完成了它的使命,去寻找它新的归宿. 题目描述 给出一个有向无环图,起点为1终点为N,每条边都有一个长度,并且从起点出 ...
- 从APNIC提取IP信息
从APNIC提取IP信息 https://blog.csdn.net/nullzeng/article/details/17538009 Apnic介绍简而言之,Apnic是全球5个地区级的Inter ...