T1 子矩阵

题目描述

小A有一个N×M的矩阵,矩阵中1~N*M这(N*M)个整数均出现过一次。现在小A在这个矩阵内选择一个子矩阵,其权值等于这个子矩阵中的所有数的最小值。小A想知道,如果他选择的子矩阵的权值为i(1<=i<=N×M),那么他选择的子矩阵可能有多少种?小A希望知道所有可能的i值对应的结果,但是这些结果太多了,他算不了,因此他向你求助。

输入格式:

第一行,两个整数N, M。

接下来的N行,每行M个整数,表示矩阵中的元素。

输出格式:

N×M行,每行一个整数,其中第i行的整数表示如果小A选择的子矩阵权值为i,他选择的子矩阵的种类数。

输入样例#1:

2 3

2 5 1

6 3 4

输出样例#1:

6

4

5

1

1

1

题解:

部分枚举,扫描列的典型模型

枚举两个行数i,j(规定i <= j),寻找[i,j]行内的矩形

递推可得[i,j]行内每一列的最小值

维护单调递增的栈,计算L[k](在[i,j]行内选择第k列,则向左最远能够选到L[k]列),R[i](在[i,j]行内选择第k列,则向右最远能够选到R[k]列)

乘法原理得到左右行数在[i,j]内的、包含第k列的子矩阵

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
inline void read(int &x){x = 0;char ch = getchar();char c = ch;while(ch > '9' || ch < '0')c = ch, ch = getchar();while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0',ch = getchar();if(c == '-')x = -x;}
inline void swap(int &a, int &b){int tmp = a;a = b;b = tmp;}
inline int max(int a, int b){return a > b ? a : b;}
inline int min(int a, int b){return a < b ? a : b;} const int INF = 0x3f3f3f3f;
const int MAXN = 5000 + 10;
const int MAXM = 100000; int n,m,num[MAXN][MAXN];
int stack[MAXM], top;
int mi[MAXM];
int L[MAXM],R[MAXM];
int ans[MAXM]; int main()
{
read(n);read(m);
for(int i = 1;i <= n;++ i)
for(int j = 1;j <= m;++ j)
read(num[i][j]);
//枚举上面的行i
for(register int i = 1;i <= n;++ i)
{
//注意清为最大值
memset(mi, 0x3f, sizeof(mi)); //枚举i以下的行j
for(register int j = i;j <= n;++ j)
{
//求得行[i,j]范围内的每一列的最小值
for(register int k = 1;k <= m;++ k)
mi[k] = min(mi[k], num[j][k]); //正向扫描求R,维护一个递增(或相等)单调栈
for(register int k = 1;k <= m;++ k)
{
while(top && mi[k] < mi[stack[top]])
{
R[stack[top]] = k - 1;
-- top;
}
stack[++top] = k;
}
while(top)
{
R[stack[top]] = m;
-- top;
} //反向扫描求L,维护一个递增(或相等)单调栈
for(int k = m;k >= 1;k --)
{
while(top && mi[k] < mi[stack[top]])
{
L[stack[top]] = k + 1;
-- top;
}
stack[++top] = k;
}
while(top)
{
L[stack[top]] = 1;
-- top;
} //扫描列,累加答案
for(register int k = 1;k <= m;k ++)
{
ans[mi[k]] += (k - L[k] + 1) * (R[k] - k + 1);
}
}
}
register int tmp = n * m;
for(register int i = 1;i <= tmp;++ i)
{
printf("%d\n", ans[i]);
}
return 0;
}

T2 序列操作

题目描述

小B有一个整数序列a[1..N],初始时序列中所有元素均为0。他会在序列上进行下面两种操作,操作共M个:

1、A l r x:将a[l..r]均加上x。

2、Q l r:询问a[l..r]中的最大值。

输入格式:

第一行,两个整数N, M。

接下来的M行,每行一个操作。

输出格式:

设询问操作有T个,则输出T行,每行一个整数,表示询问操作对应的答案。

输入样例#1:

5 5

A 1 4 1

A 2 5 2

Q 1 4

A 3 4 -2

Q 3 5

输出样例#1:

3

2

题解:线段树裸题

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <algorithm>
inline void read(int &x){x = 0;char ch = getchar();char c = ch;while(ch > '9' || ch < '0')c = ch, ch = getchar();while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0',ch = getchar();if(c == '-')x = -x;}
inline void swap(int &a, int &b){int tmp = a;a = b;b = tmp;}
inline int max(int a, int b){return a > b ? a : b;}
inline int min(int a, int b){return a < b ? a : b;} const int INF = 0x3f3f3f3f;
const int MAXN = 100000 + 10;
const int MAXM = 100000 + 10; int sgtmax[MAXN];
int sgtlazy[MAXN];
int n,m; inline void putdown(int& o, int& l, int& r)
{
sgtmax[o << 1] += sgtlazy[o];
sgtlazy[o << 1] += sgtlazy[o];
sgtlazy[o << 1 | 1] += sgtlazy[o];
sgtmax[o << 1 | 1] += sgtlazy[o];
sgtlazy[o] = 0;
} void modify(int ll, int rr, int k, int o = 1, int l = 1, int r = n)
{
if(ll <= l && rr >= r)
{
sgtmax[o] += k;
sgtlazy[o] += k;
return;
}
int mid = (l + r) >> 1;
if(sgtlazy[o])putdown(o, l, r);
if(mid >= ll)modify(ll, rr, k, o << 1, l, mid);
if(mid < rr)modify(ll, rr, k, o << 1 | 1, mid + 1, r);
sgtmax[o] = max(sgtmax[o << 1], sgtmax[o << 1 | 1]);
} int ask(int ll, int rr, int o = 1, int l = 1, int r = n)
{
if(ll <= l && rr >= r)
{
return sgtmax[o];
}
int mid = (r + l) >> 1;
if(sgtlazy[o])putdown(o, l, r);
int ans = -INF;
if(mid >= ll)ans = max(ans, ask(ll, rr, o << 1, l, mid));
if(mid < rr)ans = max(ans, ask(ll, rr, o << 1 | 1, mid + 1, r));
return ans;
} int main()
{
read(n);read(m);
register int i,tmp1,tmp2,tmp3;
register char c;
for(i = 1;i <= m;i ++)
{
c = getchar();
while(c != 'A' && c != 'Q')c = getchar();
if(c == 'A')
{
read(tmp1);read(tmp2);read(tmp3);
modify(tmp1, tmp2, tmp3);
}
else
{
read(tmp1);read(tmp2);
printf("%d\n", ask(tmp1, tmp2));
}
}
return 0;
}

T3 议案决定

题目描述

小C在玩一个游戏,在游戏中他扮演国王的角色。国王手下有M个大臣,他们有一天对国王要处理的N件事务进行投票。 每个大臣可以对两件事务进行投票(赞成或反对),格式如下:x c_x y c_y(x, y为整数,c_x, c_y为“Y”(表示赞成)或“N”(表示反对)(不含双引号),表示这个大臣对事务x的态度为c_x,对事务y的态度为c_y)。这些大臣非常难以对付,如果国王的决定和某个大臣的两个意见都不同,那么这个大臣就会离开国王。小C认为不能让任何一个大臣离开国王,否则国王就无法正常地处理自己的事务。 请你帮助小C做个决定。

输入格式:

第一行,两个整数N, M。

接下来的M行,每行表示一个大臣的投票。

输出格式:                      

如果小C无论如何都只能让至少一个大臣离开国王,则输出“IMPOSSIBLE”(不含双引号),否则输出一个长度为N的字符串 ,如果第i件事务必须赞成,则第i个字符为“Y”;如果第i件事务必须反对,则第i个字符为“N”,否则第i个字符为“?”。

输入样例#1:

3 4

1 Y 2 N

1 N 2 N

1 Y 2 Y

输出样例#1:

YN?

题解:

经典2-SAT问题

点u->v代表u发生则v必然发生

每一个条件可以拆为这样的两个条件

如1 Y 2 N  对应的是  1N->2N   2Y->1Y

我们把1Y  1N称为对立节点

符合条件的情况是,从节点i出发找一条路径,路径上不会遇到i的对立节点。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <algorithm> const int MAXN = 80000 + 10; inline void read(int &x){x = 0;char ch = getchar();char c = ch;while(ch > '9' || ch < '0')c = ch, ch = getchar();while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();if(c == '-')x = -x;}
inline void read(char& x){x = 0;while(x != 'Y' && x != 'N')x = getchar();} struct Edge{int u,v,next;}edge[MAXN << 1];
int head[MAXN << 1],cnt;
void insert(int a, int b){edge[++cnt] = Edge{a,b,head[a]};head[a] = cnt;} int n,m; int ans[MAXN]; //Y:ou shu N:ji shu int match[MAXN << 1]; int dfs(int u)
{
for(int pos = head[u];pos;pos = edge[pos].next)
{
int v = edge[pos].v;
if(!v || v == 1)continue;
if(v & 1)
{
if(match[v - 1])return 0;
if(match[v])continue;
match[v] = 1;
int tmp = dfs(v);
if(!tmp) return 0;
}
else
{
if(match[v | 1])return 0;
if(match[v])continue;
match[v] = 1;
int tmp = dfs(v);
if(!tmp)return 0;
}
}
return 1;
} inline int check(int i)
{
memset(match, 0, sizeof(match));
match[i] = 1;
return dfs(i);
} const char a[3] = {'?', 'Y', 'N'}; int main()
{
read(n);read(m);
register char c1,c2;register int tmp1, tmp2;
register int i;
for(i = 1;i <= m;++ i)
{
read(tmp1);read(c1);read(tmp2);read(c2);
if(c1 == 'Y' && c2 == 'N')
{
insert(tmp1 << 1 | 1, tmp2 << 1 | 1);
insert(tmp2 << 1, tmp1 << 1);
}
else if(c1 == 'Y' && c2 == 'Y')
{
insert(tmp2 << 1 | 1, tmp1 << 1);
insert(tmp1 << 1 | 1, tmp2 << 1);
}
else if(c1 == 'N' && c2 == 'N')
{
insert(tmp2 << 1, tmp1 << 1 | 1);
insert(tmp1 << 1, tmp2 << 1 | 1);
}
else if(c1 == 'N' && c2 == 'Y')
{
insert(tmp2 << 1 | 1, tmp1 << 1 | 1);
insert(tmp1 << 1, tmp2 << 1);
}
} for(i = 1;i <= n;i ++)
{
tmp1 = check(i << 1);
tmp2 = check(i << 1 | 1);
if(tmp1 && tmp2)ans[i] = 0;
else if(tmp1)ans[i] = 1;
else if(tmp2)ans[i] = 2;
else
{
printf("IMPOSSIBLE");
return 0;
}
} for(int i = 1;i <= n;i ++)
{
printf("%c", a[ans[i]]);
}
return 0;
}

NOIP模拟 6.26的更多相关文章

  1. 8.19 NOIP模拟测试26(B) 嚎叫响彻在贪婪的厂房+主仆见证了 Hobo 的离别+征途堆积出友情的永恒

    T1 嚎叫响彻在贪婪的厂房 以前做过一个等比数列的题「序列」,这个类似 是等差数列且公差不为1的条件就是各项差的绝对值的$gcd!=1$,每次拿出序列前两个数,求出差值,插入到set里,每次向后扩展, ...

  2. NOIP模拟测试26「嚎叫响彻在贪婪的机房·主仆见证了 Hobo 的离别·征途堆积出友情的永恒」

    题目比较神仙,注意是题目神仙 贪婪暗示贪心,堆积暗示堆优化$\%\%\%\%\%\%\%$ 两个乱搞$+$一个堆优化$dp$ 嚎叫响彻在贪婪的机房 题解 对于一个序列来说只要他们差的$gcd$不为$1 ...

  3. noip模拟26[肾炎黄·酱累黄·换莫黄]

    \(noip模拟26\;solutions\) 这个题我做的确实是得心应手,为啥呢,因为前两次考试太难了 T1非常的简单,只不过我忘记了一个定理, T2就是一个小小的线段树,虽然吧我曾经说过我再也不写 ...

  4. NOIP模拟题17.9.26

    B 君的任务(task)[题目描述]与君初相识,犹如故人归.B 君看到了Z 君的第一题,觉得很难.于是自己出了一个简单题.你需要完成n 个任务,第i 任务有2 个属性ai; bi.其中ai 是完成这个 ...

  5. 2014-10-31 NOIP模拟赛

        10.30 NOIp  模拟赛   时间 空间 测试点 评测方式 挖掘机(dig.*) 1s 256M 10 传统 黑红树(brtree.*) 2s 256M 10 传统 藏宝图(treas. ...

  6. NOIP模拟 1

    NOIP模拟1,到现在时间已经比较长了.. 那天是6.14,今天7.18了 //然鹅我看着最前边缺失的模拟1,还是终于忍不住把它补上,为了保持顺序2345重新发布了一遍.. #   用  户  名   ...

  7. 8.1 NOIP模拟11

    8.1 NOIP模拟 11 今天上午返校之后,颓了一会,然后下午就开始考试,中午睡着了,然后刚开始考试的时候就困的一匹,我一看T1,woc,这不是之前线段树专题的题啊,和那道题差不多,所以我..... ...

  8. NOIP模拟17.9.22

    NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥

  9. NOIP模拟 17.8.17

    NOIP模拟17.8.17 A 小 G 的字符串文件名 输入文件 输出文件 时间限制 空间限制str.pas/c/cpp str.in str.out 1s 128MB[题目描述]有一天,小 L 给小 ...

随机推荐

  1. shell学习笔记2: shell中的四则运算符

    shell中的四则运算符 n1,n2 :常量数字 char:运算符号 加,减,乘,除,取余(+,-,*,/,%) $a,$b:变量a,变量b 方法1 数字与符号之间需要有空格 不支持小数 expr n ...

  2. 菜鸟nginx源码剖析数据结构篇(一)动态数组ngx_array_t[转]

    菜鸟nginx源码剖析数据结构篇(一)动态数组ngx_array_t Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.csdn ...

  3. SpringCloud学习笔记(三):Rest微服务构建案例工程模块

    需要具备的知识 1 springmvc+mybatis+mysql 2 Consumer消费者(Client)通过REST调用Provider提供者(Server)提供的服务 3 Maven的分包分模 ...

  4. 关于mybatis对实体类参数绑定参数的问题

    dao层的代码: public interface SupplierMapper extends BaseMapper<SupplierDbo>{ /*List<SupplierDb ...

  5. springboot自己实现mysql主从数据切换机制

    在很多公司都是实现了数据的读写分离,所谓的读写分离,就是写的时候从主库 ,然后从库就会从主库中复制过去,这样就会形成了数据的读写分离,然而在很多场景是适用的,那么我们怎么做呢,可以利用aop 加注解的 ...

  6. mybatis配合pagehelper分页助手查询

    Maven: 参考: springBoot2.x整合pagehelper5.1.2:https://blog.csdn.net/Carlson_Chis/article/details/8563748 ...

  7. 全栈之路-微信小程序-SKU开发(代码)

    SKU开发是小程序中最难的一部分,思路在分析中已经记录过了,这里主要看一下代码的实现,感觉老师写的代码太棒了,很优雅!主要想记录一下写代码的思路,对面向对象编程的实践. 一.代码结构的分析 1.说明几 ...

  8. watch、tail联合使用

    因为用了tmux,不想调整窗格大小,只想输出命令结果的最后几行,所以就想出了这个方法. watch.tail联合用法 watch 'echo "`nvidia-smi`" | ta ...

  9. PAT甲级——A1019 General Palindromic Number

    A number that will be the same when it is written forwards or backwards is known as a Palindromic Nu ...

  10. python实例5-表格打印

    编写一个名为printTable()的函数,它接受字符串的列表的列表,将它显示在组织良好的表格中,每列右对齐.假定所有内层列表都包含同样数目的字符串.例如,该值可能看起来像这样: table_data ...