【题目描述】

    一个长为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. PAT 甲级 1101 Quick Sort

    https://pintia.cn/problem-sets/994805342720868352/problems/994805366343188480 There is a classical p ...

  2. Windows Sever 2008隐藏和系统属性

    由于有些目录为隐藏和系统属性,首先要把 显示系统文件和显示所有文件 功能开启,把隐藏文件和目录显出来. 1.C:\Windows\Web\Wall*** 自带墙纸,不需要的可以删除掉. 2.C:\Wi ...

  3. redis——持久化方式RDB与AOF分析

    https://blog.csdn.net/u014229282/article/details/81121214 redis两种持久化的方式 RDB持久化可以在指定的时间间隔内生成数据集的时间点快照 ...

  4. c++源文件到可执行文件的过程

    1.预处理(preprocessor):对#pragma.#include.#define.#ifdef/#endif.#ifndef/#endif,inline内联函数等进行处理 2.编译(comp ...

  5. 求助 delphi ADO组件的 CursorLocation属性设置为 clUseServer 用法 [问题点数:20分]

    我有个管理系统,所有ADOQUERY组件的 CursorLocation属性设置为 clUseClient,一直运行正常,我尝试全部设置为clUseServer, 系统不运行了,请大家帮忙. 我的做法 ...

  6. ConcurrentHashMap弱一致性

    [原文链接] 本文将用到Java内存模型的happens-before偏序关系(下文将简称为hb)以及ConcurrentHashMap的底层模型相关的知识.happens-before相关内容参见: ...

  7. 第72天:jQuery实现下拉菜单

    jQuery实现下拉菜单 一.居中 1.块元素居中:给块元素本身设置:margin:0 auto;,块元素必须设置宽度 2.行内块元素居中:给元素父级设置text-algin:center; < ...

  8. BZOJ2428:[HAOI2006]均分数据——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=2428 https://www.luogu.org/problemnew/show/P2503 已知 ...

  9. Visio分类

    以编程方式使用 Microsoft Office Visio 2003 ActiveX 控件 visio应用程序相关设置-选项-视图 visio应用程序相关设置-选项-常规 visio中相关设置-菜单 ...

  10. 洛谷 P1527 [国家集训队]矩阵乘法 解题报告

    P1527 [国家集训队]矩阵乘法 题目描述 给你一个\(N*N\)的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第\(K\)小数. 输入输出格式 输入格式: 第一行两个数\(N,Q\),表示矩阵大 ...