T1:

把每一行状压,按行DP。设fi,j,k,i表示第几行,j是当前行的1覆盖状态,k是当前行选择按钮的状态。转移的时候枚举j和k,再枚举下一层的按钮选择情况l。如果l和j可以全覆盖当前层则转移合法,根据下一层选择l状态的代价进行转移。预处理一行每一种选法i可以覆盖到的状态di,各行选择按钮状态i对应的代价dpi,以及每一行的初始状态bi。转移时下一层的覆盖情况就是k|dl|bi+1。初始化第一层是所有选法i对应的代价,即f1,d[i]|b[1],i=dp1,i

整个DP过程的复杂度是O(3m*2m*n)。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=,maxn=<<N;
int n,maxx,ans,m,flag;
int s[N][N],a[N][N],dp[N][maxn],f[N][maxn][maxn],b[N],d[maxn];
int main()
{
scanf("%d%d",&n,&m);
maxx=<<m;
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
scanf("%1d",&s[i][j]);
b[i]|=(s[i][j]<<(j-));
}
}
for(int i=;i<maxx;i++){
d[i]=(i|(i<<)|(i>>))&(maxx-);
}
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
scanf("%d",&a[i][j]);
}
for(int j=;j<maxx;j++){
for(int k=;k<=m;k++){
if(j&(<<(k-))){
dp[i][j]+=a[i][k];
}
}
}
}
memset(f,0x3f3f3f3f,sizeof(f));
for(int j=;j<maxx;j++){
f[][d[j]|b[]][j]=min(f[][d[j]|b[]][j],dp[][j]);
}
for(int i=;i<n;i++){
for(int j=;j<maxx;j++){
if((j&b[i])!=b[i])continue;
for(int k=j;k>=;k=(k-)&j){
if((d[k]&j)!=d[k]&&k)continue;
for(int l=;l<maxx;l++){
if((j|l)==(maxx-)){
f[i+][d[l]|k|b[i+]][l]=min(f[i+][d[l]|k|b[i+]][l],f[i][j][k]+dp[i+][l]);
}
}
if(!k)break;
}
}
}
ans=0x3f3f3f3f;
for(int i=;i<maxx;i++)ans=min(ans,f[n][maxx-][i]);
printf("%d\n",ans);
return ;
}

处理b的时候反着处理了整张图,并且初始化第一行的时候出了锅没考虑b数组,于是写了一下午。

T2:

第一问比较容易。把求方案数的过程看成一个往序列里添加元素的过程。将原序列按第一关键字val从大到小,第二关键字key从小到大排序。val从大到小保证了后添加的元素无论放在哪都不会影响前面放进来的元素,并且已经存在的每一个元素都会对当前元素的key值产生贡献。所以只用考虑当前要放的元素本身的限制,考虑怎么求这一次操作的方案数,即新加入的元素能放在哪些地方。如果序列里的元素个数小于keyi,那么显然最多只有i个位置可以放(1->i)。如果序列里的元素多于等于keyi个,那么也只有前keyi个位置可以放,这样才不会超出key的限制。特别的状况是存在相同的val,这就是前面key作为第二关键字从小到大排序的原因。相同val的key从小到大,保证对于后加入的元素,先加入的val相同的元素所在的位置也可以放当前的元素。先加入的元素为后加入的元素创造了新的位置,它所在的地方后加入的元素一定可以放到。于是对于相同的val累计一个num,num从已有的第二个相同val开始累计,ans=(ans*min(i,keyi+num))%mod。

第二问愣是没想出来,也没看明白题解里平衡树的做法。好像是根据第一问的过程,每次插入一个元素的时候,贪心地放在能放的最大位置之前的第一个字典序比它大的元素前面。然后就不会写了。

题解的第二种做法是利用线段树,也是贪心地构造一个序列。一开始所有元素都是未加入元素。如果已经加入的元素的个数小于手中所有元素的key值-1,那么随便把哪个元素扔进序列都合法。根据题目要求,显然选择未加入的元素中字典序最小的。如果未加入的元素中存在key被卡在界限上,那么要么把它丢进序列,要么在val小于等于它的元素中选择更优的丢进序列。于是可以想到把原序列按val第一关键字从小到大key第二关键字从小到大排序,用线段树维护序列。选择要加入序列的元素就是在线段树的一段区间上选择key最小的元素。每次将一个元素扔进序列后,把线段树上这个元素的所有信息都变成inf,并且把所有未加入序列且val比它小的元素的key值-1,即线段树上的区间减。这里的key其实要记两次,一个记作用来当作限制,进行区间减操作。一个始终不变,用来在区间查询的时候作为可能答案进行比较。更新区间最小限制值以及key值的时候若出现值相同的元素,更新为在线段树上更靠前的,也就是val更小的。一个是构造的序列要求第二关键字val也是从小到大。另一个是若有多个key值同时等于1,要用val最小的来限制答案。否则根据更大的val选择出来的答案可能不满足val小的key的限制。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,mod=1e9+,num;
const int N=*1e5+,inf=;
long long ans;
struct node{
int key,val;
}a[N];
struct tree{
int l,r,dic,dici,val,vali,tag,top,topi;
}b[N*];
bool cmp(node a,node b){
if(a.val>b.val)return true;
else if(a.val==b.val){
if(a.key<b.key)return true;
else return false;
}
else return false;
}
bool cmp1(node a,node b){
if(a.val<b.val)return true;
else if(a.val==b.val){
if(a.key<b.key)return true;
else return false;
}
else return false;
}
void pushup(int p){
if(b[p*].dic<b[p*+].dic){
b[p].dic=b[p*].dic;
b[p].dici=b[p*].dici;
}
else if(b[p*].dic==b[p*+].dic){
b[p].dic=b[p*].dic;
if(b[p*].dici<b[p*+].dici){
b[p].dici=b[p*].dici;
}
else b[p].dici=b[p*+].dici;
}
else{
b[p].dic=b[p*+].dic;
b[p].dici=b[p*+].dici;
}
if(b[p*].val<b[p*+].val){
b[p].val=b[p*].val;
b[p].vali=b[p*].vali;
}
else if(b[p*].val==b[p*+].val){
b[p].val=b[p*].val;
if(a[b[p*].vali].key<a[b[p*+].vali].key){
b[p].vali=b[p*].vali;
}
else{
b[p].vali=b[p*+].vali;
}
}
else{
b[p].val=b[p*+].val;
b[p].vali=b[p*+].vali;
}
if(b[p*].top<b[p*+].top){
b[p].top=b[p*].top;
b[p].topi=b[p*].topi;
}
else if(b[p*].top==b[p*+].top){
b[p].top=b[p*].top;
if(b[p*].topi<b[p*+].topi){
b[p].topi=b[p*].topi;
}
else b[p].topi=b[p*+].topi;
}
else{
b[p].top=b[p*+].top;
b[p].topi=b[p*+].topi;
}
}
void pushdown(int p){
if(b[p].tag){
b[p*].tag+=b[p].tag;
b[p*].dic-=b[p].tag;
b[p*+].tag+=b[p].tag;
b[p*+].dic-=b[p].tag;
b[p].tag=;
}
}
void build(int p,int l,int r){
b[p].l=l,b[p].r=r;
if(l==r){
b[p].dic=a[l].key,b[p].dici=l;
b[p].val=a[l].val,b[p].vali=l;
b[p].top=a[l].key,b[p].topi=l;
return;
}
int mid=(l+r)/;
build(p*,l,mid);
build(p*+,mid+,r);
pushup(p);
}
void change(int p,int l,int r,int y){
if(l<=b[p].l&&b[p].r<=r){
b[p].dic=b[p].val=b[p].top=y;
a[b[p].l].key=y;
return;
}
pushdown(p);
int mid=(b[p].l+b[p].r)/;
if(l<=mid)change(p*,l,r,y);
if(r>mid)change(p*+,l,r,y);
pushup(p);
}
void change1(int p,int l,int r,int y){
if(l<=b[p].l&&b[p].r<=r){
b[p].dic--;
b[p].tag++;
return;
}
pushdown(p);
int mid=(b[p].l+b[p].r)/;
if(l<=mid)change1(p*,l,r,y);
if(r>mid)change1(p*+,l,r,y);
pushup(p);
}
int ask(int p,int l,int r){
if(l<=b[p].l&&b[p].r<=r){
return b[p].topi;
}
pushdown(p);
int mid=(b[p].l+b[p].r)/;
int x=;
a[x].key=a[x].val=inf;
if(l<=mid){
int y=ask(p*,l,r);
if(a[y].key<a[x].key)x=y;
else if(a[y].key==a[x].key){
if(a[y].val<a[x].val)x=y;
}
}
if(r>mid){
int y=ask(p*+,l,r);
if(a[y].key<a[x].key)x=y;
else if(a[y].key==a[x].key){
if(a[y].val<a[x].val)x=y;
}
}
pushup(p);
return x;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d%d",&a[i].key,&a[i].val);
}
sort(a+,a+n+,cmp);
ans=;
for(int i=;i<=n;i++){
if(i>&&a[i].val==a[i-].val)num++;
else num=;
ans=ans*min(i,a[i].key+num)%mod;
}
printf("%lld\n",ans);
sort(a+,a+n+,cmp1);
build(,,n);
for(int i=,x;i<=n;i++){
if(b[].dic==)x=ask(,,b[].dici);
else x=b[].topi;
printf("%d %d\n",a[x].key,a[x].val);
if(x>)change1(,,x-,-);
change(,x,x,inf);
}
return ;
}

第一问没想多长时间,第二问也没改多长时间(至少比我作为全场倒数改出来的T1要强),但是考场上就是没想出第二问怎么写。按理说贪心的思路也不是很难想…

T3:

不会,没写,咕着。

关于像在长郡考试那次一样把自己的电脑卡死机两次还不得不关机一次这件事情我还能说什么呢我给自己找扇窗户吧

关于T1不好好打暴力搜索非要搞玄学状压搜索这件事情我都不用给自己找扇窗户了就地蒸发吧

菜 墨雨笙 菜

2019.10.21 csp-s模拟测试81 反思总结的更多相关文章

  1. 2019.8.3 [HZOI]NOIP模拟测试12 C. 分组

    2019.8.3 [HZOI]NOIP模拟测试12 C. 分组 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 刚看这题觉得很难,于是数据点分治 k只有1和2两种,分别 ...

  2. 2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci)

    2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci) 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 找规律 找两个节点的lca,需 ...

  3. 2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色

    2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 数据结构学傻的做法: 对每种颜色开动态开点线段树直接维 ...

  4. 2019.10.29 CSP%您赛第四场t2

    我太菜了我竟然不会分层图最短路 ____________________________________________________________________________________ ...

  5. 2019.8.9 NOIP模拟测试15 反思总结

    日常爆炸,考得一次比一次差XD 可能还是被身体拖慢了学习的进度吧,虽然按理来说没有影响.大家听的我也听过,大家学的我也没有缺勤多少次. 那么果然还是能力问题吗……? 虽然不愿意承认,但显然就是这样.对 ...

  6. 2019.8.1 NOIP模拟测试11 反思总结

    延迟了一天来补一个反思总结 急匆匆赶回来考试,我们这边大家的状态都稍微有一点差,不过最后的成绩总体来看好像还不错XD 其实这次拿分的大都是暴力[?],除了某些专注于某道题的人以及远程爆踩我们的某学车神 ...

  7. 2019/10/17 CSP模拟 总结

    T1 补票 Ticket 没什么好说的,不讲了 T2 删数字 Number 很后悔的是其实考场上不仅想出了正解的方程,甚至连优化都想到了,却因为码力不足只打了\(O(n^2)\)暴力,甚至还因为细节挂 ...

  8. 2019.10.30 csp-s模拟测试94 反思总结

    头一次做图巨的模拟题OWO 自从上一次听图巨讲课然后骗了小礼物以后一直对图巨印象挺好的233 T1: 对于XY取对数=Y*log(x) 对于Y!取对数=log(1*2*3*...*Y)=log1+lo ...

  9. 2019.8.10 NOIP模拟测试16 反思总结【基本更新完毕忽视咕咕咕】

    一如既往先放代码,我还没开始改… 改完T1滚过来了,先把T1T2的题解写了[颓博客啊] 今天下午就要走了,没想到还有送行的饯别礼,真是欣喜万分[并没有] 早上刚码完前面的总结,带着不怎么有希望的心情开 ...

随机推荐

  1. BZOJ2594:水管局长数据加强版

    Description SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从x处送往y处,嘟嘟需要为供水公司找到一 ...

  2. vue爬坑之input组件

    本篇写给第一次用VUE写输入框组件的朋友们 正常情况我们vue2.0是怎么样取到input框的值的呢? 很简单只需要给input框设置v-model="val" 我们就能从data ...

  3. localStorage,sessionStorage,cookie区别

    localStorage:HTML5新增的在浏览器端存储数据的方法.设置和获取localStorage的方法: 设置: localStorage.name = 'zjj'; 获取: localStor ...

  4. [不知道出自什么OJ]最大利润

    题目描述 政府邀请了你在火车站开饭店,但不允许同时在两个相连接的火车站开.任意两个火车站有且只有一条路径,每个火车站最多有50个和它相连接的火车站. 告诉你每个火车站的利润,问你可以获得的最大利润为多 ...

  5. PAT甲级——A1076 Forwards on Weibo

    Weibo is known as the Chinese version of Twitter. One user on Weibo may have many followers, and may ...

  6. 分布式事务的2PC、3PC和TCC

    1.2PC协议 2PC 是二阶段提交(Two-phase Commit)的缩写,顾名思义,这个协议分两阶段完成.第一个阶段是准备阶段,第二个阶段是提交阶段,准备阶段和提交阶段都是由事务管理器(协调者) ...

  7. Django项目: 项目环境搭建 ---- 二、django项目设置

    1.配置模板文件 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.p ...

  8. Nginx报错汇总

    1.     Nginx 无法启动解决方法 在查看到 logs 中报了如下错误时: 0.0.0.0:80 failed (10013: An attempt was made to access a ...

  9. 如何使用log4j记录日志

    1.下载jar包 http://logging.apache.org/log4j 2.将jar包加入项目 放在lib(没有就创建)下 对已经复制过来的jar包鼠标点击右键,选中BuildPath  - ...

  10. [转]深入WPF--Style

    Style 用来在类型的不同实例之间共享属性.资源和事件处理程序,您可以将 Style 看作是将一组属性值应用到多个元素的捷径. 这是MSDN上对Style的描述,翻译的还算中规中矩.Style(样式 ...