【题目描述】

    一个长为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+线段树维护的更多相关文章

  1. 小C的填数游戏

    题意: 给出一张n个点的无向图 i连向i-1和i-2 边权为wij 有两个点权ai和bi ai为0或1 在给m个操作 1.将ai异或1 2.将区间x到y的点都填上一个数ci 使得Σ(bi*(ai^ci ...

  2. 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 ...

  3. [动态dp]线段树维护转移矩阵

    背景:czy上课讲了新知识,从未见到过,总结一下. 所谓动态dp,是在动态规划的基础上,需要维护一些修改操作的算法. 这类题目分为如下三个步骤:(都是对于常系数齐次递推问题) 1先不考虑修改,不考虑区 ...

  4. 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 ...

  5. bzoj 1594: [Usaco2008 Jan]猜数游戏——二分+线段树

    Description 为了提高自己低得可怜的智商,奶牛们设计了一个新的猜数游戏,来锻炼她们的逻辑推理能力. 游戏开始前,一头指定的奶牛会在牛棚后面摆N(1 <= N<= 1,000,00 ...

  6. 【bzoj1594-猜数游戏】线段树

    题解: 矛盾只有两种情况: 一.先前确定了x在区间(l,r),但是现在发现x在区间(l1,r1),并且两个区间不相交. 二.一个区间的最小值是x,这个区间中有一个子区间的最小值比x更小. 首先可以明确 ...

  7. DP+线段树维护矩阵(2019牛客暑期多校训练营(第二场))--MAZE

    题意:https://ac.nowcoder.com/acm/contest/882/E 给你01矩阵,有两种操作:1是把一个位置0变1.1变0,2是问你从第一行i开始,到最后一行j有几种走法.你只能 ...

  8. Codeforces 833B 题解(DP+线段树)

    题面 传送门:http://codeforces.com/problemset/problem/833/B B. The Bakery time limit per test2.5 seconds m ...

  9. @NOIP2018 - D2T2@ 填数游戏

    目录 @题目描述@ @题解@ @代码@ @题目描述@ 小 D 特别喜欢玩游戏.这一天,他在玩一款填数游戏. 这个填数游戏的棋盘是一个 n×m 的矩形表格.玩家需要在表格的每个格子中填入一个数字(数字 ...

随机推荐

  1. Activemq 消息类型 (转)

    Activemq消息类型JMS规范中的消息类型包括TextMessage.MapMessage.ObjectMessage.BytesMessage.和StreamMessage等五种.ActiveM ...

  2. php mongodb扩展 其他扩展也类似

    MongoDBPHP 扩展 本教程将向大家介绍如何在Linux.window.Mac平台上安装MongoDB扩展. Linux上安装 MongoDB PHP扩展 在终端上安装 你可以在linux中执行 ...

  3. jCanvaScript canvas的操作库

    在jcscript.com上下载最新的jCanvaScript.1.5.18.min.js文件  里面有很多关于canvas的方法都已经是封装好了的,只需直接调用,但是要注意调用之前和调用之后都要写: ...

  4. asp.net mvc4中Json的应用

    做一个简单的 Json实例,从页面获取后台的Json数据 1.控制台: public class HomeController : Controller { // // GET: /Home/ pub ...

  5. ASP.NET MVC4计划任务实现方法(定时执行某个功能)

    系统中定时执行某个任务是比较常用的功能,如一个部门定期向上级部门上报数据是一个典型的例子,下面就简单说说在.net mvc中如何实现定时执行某个功能的方法. 1.首先修改Glocal.asax文件,在 ...

  6. 【刷题】SPOJ 8222 NSUBSTR - Substrings

    You are given a string S which consists of 250000 lowercase latin letters at most. We define F(x) as ...

  7. 【Ubuntu】编写一个c语言代码

    安装 sudo apt-get  build-depgcc coding:http://www.cnblogs.com/zero1665/archive/2009/11/03/1595510.html ...

  8. ubuntu简易教程(如何使用noi linux)

    目录 linux环境下的基础操作 命令行操作 编辑器 程序编译 程序调试 gdb的使用 对拍 在提高组的考试中要求使用noi linux,因此了解一下如何在linux环境下编程是很有必要的. linu ...

  9. 【BZOJ5329】【SDOI2018】战略游戏(圆方树,虚树)

    [BZOJ5329][SDOI2018]战略游戏(圆方树,虚树) 题面 BZOJ 洛谷 Description 省选临近,放飞自我的小Q无心刷题,于是怂恿小C和他一起颓废,玩起了一款战略游戏. 这款战 ...

  10. MySQL5.6之Index Condition Pushdown(ICP,索引条件下推)-Using index condition

    http://blog.itpub.net/22664653/viewspace-1210844/ -- 这篇博客写的更细,以后看 ICP(index condition pushdown)是mysq ...