是个神仙dp……

参考:https://www.luogu.org/blog/xzz-233/solution-p5289

设f[i][j][k]是前i个有限制的城市,所有学校中选蓝色阵营有j人,有限制的学校中鸭派系有k人的方案数;g[i][j]是前i个没有限制的城市,蓝色阵营有j人的方案数;h[i][j]是前i个没有限制的学校,鸭派系有j人的方案数

f的转移枚举当前阵营

全dp出来之后,把gh前缀和处理,然后一段一段的和f合并加到ans上

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int N=2505,mod=998244353;
int T,n,c,c0,c1,d0,d1,k,m,ss,ans,b[N],s[N],f[N][N],f1[N][N],f2[N][N],g[N],h[N],ki[N],kp[N],v[N],ct[N],sum[N],sm[N];
vector<int>sc[N];
void jia(int &x,int y)
{
if((x+=y)>=mod)
x-=mod;
}
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
int main()
{
T=read();
while(T--)
{
memset(f,0,sizeof(f));
memset(f1,0,sizeof(f1));
memset(f2,0,sizeof(f2));
memset(g,0,sizeof(g));
memset(h,0,sizeof(h));
memset(sm,0,sizeof(sm));
memset(sum,0,sizeof(sum));
memset(ct,0,sizeof(ct));
for(int i=0;i<N;i++)
sc[i].clear();
ss=0,ans=0;
n=read(),c=read(),c0=read(),c1=read(),d0=read(),d1=read();
for(int i=1;i<=n;i++)
b[i]=read(),s[i]=read(),sum[b[i]]+=s[i],ss+=s[i];
m=k=read();
for(int i=1;i<=n;i++)
v[i]=-1;
for(int i=1;i<=k;i++)
{
ki[i]=read(),kp[i]=read();
ct[i]=b[ki[i]];
sc[b[ki[i]]].push_back(ki[i]);
v[ki[i]]=kp[i];
}
sort(ct+1,ct+1+m);
m=unique(ct+1,ct+1+m)-ct-1;
for(int i=1;i<=n;i++)
if(v[i]!=-1)
sm[b[i]]+=s[i];
f[0][0]=1;
for(int i=1,s1=0,s2=0;i<=m;i++)
{
s1=min(c0,s1+sum[ct[i]]),s2=min(d0,s2+sm[ct[i]]);
for(int o=0;o<=1;o++)
{
for(int j=0;j<=s1;j++)
for(int k=0;k<=s2;k++)
f1[j][k]=f[j][k];
for(int l=0,len=sc[ct[i]].size();l<len;l++)
{
int x=sc[ct[i]][l];
for(int j=s1;j>=0;j--)
for(int k=s2;k>=0;k--)
{
if(o==0)
{
f1[j][k]=0;
if(v[x]!=1&&j>=s[x])
jia(f1[j][k],f1[j-s[x]][k]);
if(v[x]!=0&&j>=s[x]&&k>=s[x])
jia(f1[j][k],f1[j-s[x]][k-s[x]]);
}
else
{
if(v[x]==3)
f1[j][k]=0;
if(v[x]!=2&&k>=s[x])
jia(f1[j][k],f1[j][k-s[x]]);
}
}
}
if(o==0)
{
int nw=sum[ct[i]]-sm[ct[i]];
for(int j=s1;j>=0;j--)
for(int k=s2;k>=0;k--)
{
if(j>=nw)
f1[j][k]=f1[j-nw][k];
else
f1[j][k]=0;
}
for(int j=0;j<=s1;j++)
for(int k=0;k<=s2;k++)
f2[j][k]=f1[j][k];
}
else
{
for(int j=0;j<=s1;j++)
for(int k=0;k<=s2;k++)
f[j][k]=(f1[j][k]+f2[j][k])%mod;
}
}
}
g[0]=1;
for(int i=1,smm=0;i<=c;i++)
if(sc[i].empty()&&sum[i])
{
smm=min(c0,smm+sum[i]);
for(int j=smm;j>=0;j--)
if(j>=sum[i])
jia(g[j],g[j-sum[i]]);
}
h[0]=1;
for(int i=1,smm=0;i<=n;i++)
if(v[i]==-1)
{
smm=min(d0,smm+s[i]);
for(int j=smm;j>=0;j--)
if(j>=s[i])
jia(h[j],h[j-s[i]]);
}
for(int i=1;i<=c0;i++)
jia(g[i],g[i-1]);
for(int i=1;i<=d0;i++)
jia(h[i],h[i-1]);
for(int i=0;i<=c0;i++)
if(ss-i-c1-1<c0-i)
for(int j=0;j<=d0;j++)
if(ss-j-d1-1<d0-j)
jia(ans,1ll*f[i][j]*(g[c0-i]-(ss-i-c1-1>=0?g[ss-i-c1-1]:0)+mod)%mod*(h[d0-j]-(ss-j-d1-1>=0?h[ss-j-d1-1]:0)+mod)%mod);
printf("%d\n",(ans+mod)%mod);
}
return 0;
}

bzoj 5498: [2019省队联测]皮配【dp】的更多相关文章

  1. BZOJ 5495: [2019省队联测]异或粽子 (trie树)

    这题果然是原题[BZOJ 3689 异或之].看了BZOJ原题题解,发现自己sb了,直接每个位置维护一个值保存找到了以这个位置为右端点的第几大,初始全部都是1,把每个位置作为右端点能够异或出来的最大值 ...

  2. bzoj 5499: [2019省队联测]春节十二响【堆】

    首先看两条链怎么合并,贪心可得是从大到小取max,多条链同理 所以dfs合并子树的大根堆即可,注意为了保证复杂度,合并的时候要合并到最长链上,证明见长链剖分 #include<iostream& ...

  3. bzoj 5496: [2019省队联测]字符串问题【SAM+拓扑】

    有一个想法就是暴力建图,把每个A向有和他相连的B前缀的A,然后拓扑一下,这样的图是n^2的: 考虑优化建图,因为大部分数据结构都是处理后缀的,所以把串反过来,题目中要求的前缀B就变成了后缀B 建立SA ...

  4. bzoj 5495: [2019省队联测]异或粽子【可持久化trie+大根堆】

    和bzoj4504差不多,就是换了个数据结构 像超级钢琴一样把五元组放进大根堆,每次取一个出来拆开,(d,l,r,p,v)表示右端点为d,左端点区间为(l,r),最大区间和值为v左端点在p上 关于怎么 ...

  5. BZOJ 5495: [2019省队联测]异或粽子 可持久化trie+堆

    和超级钢琴,异或之三倍经验 $?$ 堆+贪心素质三连 $?$ 好无聊...... code: #include <bits/stdc++.h> #define N 500006 #defi ...

  6. BZOJ 5496: [2019省队联测]字符串问题 (后缀数组+主席树优化建图+拓扑排序)

    题意 略 分析 考场上写了暴力建图40分溜了-(结果只得了30分) 然后只要优化建边就行了 首先给出的支配关系无法优化,就直接A向它支配的B连边. 考虑B向以B作为前缀的所有A连边,做一遍后缀数组,两 ...

  7. BZOJ 5494: [2019省队联测]春节十二响 (左偏树 可并堆)

    题意 略 分析 稍微yy一下可以感觉就是一个不同子树合并堆,然后考场上写了一发左偏树,以为100分美滋滋.然而发现自己傻逼了,两个堆一一对应合并后剩下的一坨直接一次合并进去就行了.然鹅我这个sb把所有 ...

  8. 【BZOJ5499】[2019省队联测]春节十二响(贪心)

    [BZOJ5499][2019省队联测]春节十二响(贪心) 题面 BZOJ 洛谷 题解 如果是一条折链,显然维护两侧的值,每次两个堆分别弹出一个\(max\)然后合并一下,最后再放回去就可以了. 那么 ...

  9. bzoj 5251: [2018多省省队联测]劈配

    Description 一年一度的综艺节目<中国新代码>又开始了. Zayid从小就梦想成为一名程序员,他觉得这是一个展示自己的舞台,于是他毫不犹豫地报名了. 题目描述 轻车熟路的Zayi ...

随机推荐

  1. FLEX接收外部参数 .

    FLEX参数传递与FLASH有点不同 login..swf?name=aa&password=bb Flex上是这样接收参数的 myname=mx.core.Application.appli ...

  2. HBase技术简介

    一.HBase简介 HBase – Hadoop Database,是一个高可靠性.高性能.面向列.可伸缩的分布式存储系统,利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群. ...

  3. Android的Message Pool是个什么鬼,Message Pool会否引起OOM——源代码角度分析

    引言 Android中,我们在线程之间通信传递通常採用Android的消息机制,而这机制传递的正是Message. 通常.我们使用Message.obtain()和Handler.obtainMess ...

  4. 获取Bootstrap-Table的所有内容,修改行内容

    var allTableData = $tableLeft.bootstrapTable('getData');//获取表格的所有内容行 var flag = false; for( i=0;i< ...

  5. appium 控件定位

    转自:http://www.2cto.com/kf/201410/340345.html AppiumDriver的各种findElement方法的尝试,尝试的目标应用是SDK自带的Notepad应用 ...

  6. HDOJ_ How can I read input data until the end of file ?

    Language C C++ Pascal To read numbers int n;while(scanf("%d", &n) != EOF){ ...} int n; ...

  7. VUE 之 生命周期

    1. Vue实例的生命周期分为8个周期 1.1 beforeCreate:在实例创建前 <div id="app"> {{ name }} <button @cl ...

  8. Xamarin.Android 记事本(一)

    导读 1.视图及数据库的创建 2.listview数据绑定 3.listview的点击事件 正文 如何创建一个listview,大家可以看这里,基本流程操作是一模一样的,我就不多说了,然后就是新建一个 ...

  9. ssh原理【转】

    1 转自 http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html 2 ssh远程登陆的原理 普通用户远程登陆 ssh jason@ho ...

  10. 解决pyspark-linux-windowsIDE JAVA_HOME not set

    对 os.environ 赋值 ssh://root@192.168.2.51:22/usr/bin/python -u /home/data/tmp_test/trunk/personas/tmp_ ...