博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
18.11.2 考试总结
阅读量:5134 次
发布时间:2019-06-13

本文共 3678 字,大约阅读时间需要 12 分钟。

今天考试本暴力选手爱了

   

这道题真的签到题了... 暴力枚举所有情况a了

代码

#include 
using namespace std;const int N = 100;int n, a[N], b[N], c[N], d[N];long long ans = 0;void deal(int sta) { int oi = 0, whk = 0; for(int i = 1;i <= n;i ++) { int D = sta & (1 << (i - 1)) ? 1 : 0; if(D) { oi += c[i]; whk -= d[i]; if(whk < 0) whk = 0; } else { oi -= b[i], whk += a[i]; if(oi < 0) oi = 0; } } ans = max(ans, 1ll * oi * whk);}int main( ) { freopen("week.in", "r", stdin); freopen("week.out", "w", stdout); scanf("%d", & n); for(int i = 1; i <= n; i ++) scanf("%d%d%d%d",& a[i], & b[i], & c[i], & d[i]); for(int sta = 0; sta < (1 << n); sta ++) deal(sta); printf("%lld\n", ans);}

  

样例再次又臭又长

输入

3 4 4 1101 0110 1101 1 1 3 4 1 1 3 1 2 2 3 4 1 2 2 4

输出

3222

这道题因为他说了每两个黑色块块之间只有一条路径相连 也就是说每两个连通块之间也只有一条路径

换句话说没多一条边就减少一个连通块  连通块数 = 总点数 - 边数 

维护一个边点的二维前缀和即可

代码

#include 
using namespace std;const int N = 2000 + 5;const int M = 2e5 + 5;int n, m, q, a[N][N], R[N][N], C[N][N], nd[N][N], edg[N][N];char s[N];void Init( ) { scanf("%d%d%d",& n,& m,& q); for(int i = 1;i <= n;i ++) { scanf("%s", s + 1); for(int j = 1;j <= m;j ++) a[i][j] = s[j] - '0'; } for(int i = 1;i <= n;i ++) for(int j = 1;j <= m;j ++) { edg[i][j] = edg[i][j - 1]; nd[i][j] = nd[i][j - 1]; if(a[i][j]) nd[i][j] ++; if(a[i][j] && a[i][j - 1]) edg[i][j] ++; R[i][j] = edg[i][j]; } for(int i = 2;i <= n;i ++) for(int j = 1;j <= m;j ++) { C[i][j] = C[i - 1][j]; if(a[i][j] && a[i - 1][j]) C[i][j] ++; } for(int i = 2;i <= n;i ++) { int tmp = 0; for(int j = 1;j <= m;j ++) { nd[i][j] += nd[i - 1][j]; if(a[i][j] && a[i - 1][j]) tmp ++; edg[i][j] += edg[i - 1][j] + tmp; } }}void Solve( ) { for(int i = 1;i <= q;i ++) { int l1, r1, l2, r2; scanf("%d%d%d%d",& l1, & r1, & l2, & r2); int nds = nd[l2][r2] - nd[l2][r1 - 1] - nd[l1 - 1][r2] + nd[l1 - 1][r1 - 1]; int edgs = edg[l2][r2] - edg[l2][r1] - edg[l1][r2] + edg[l1][r1]; edgs += C[l2][r1] - C[l1][r1] + R[l1][r2] - R[l1][r1]; printf("%d\n", nds - edgs); }}int main( ) { freopen("duty.in", "r", stdin); freopen("duty.out", "w", stdout); Init( ); Solve( );}

   

     

这道题首先可以发现若两条线段$a, b$有交点 那么需要满足$ax > bx,ay < by$很容易想到使用逆序对

但是多条线交于一点呢 可以发现每与一个点相交 产生的贡献即为原本经过该点的线段数量 同样转化为相交求逆序对的问题

但是这道题数据范围直接树状数组要凉 然后我们发现对于没超过$mod$范围的点他们之间的距离成等差数列 差$a$

那么可以考虑将原序列拆成大小为$a$的块 每个块内的点数都是一样的 点数为总的轮数 每越过一次$mod$记一次

从前往后做$y$递增 所以我们每次要求的是有多少个$x$比他大 每次我们查看他是第几块 递增的求出对于当前线的逆序对的数量即可

需要特判初始$x > a$的情况 因为这时候每个块内的点数不同

代码

#include 
using namespace std;const int N = 1e5 + 5;int c[N], a, n, x, mod;long long ans;int lowbit(int pos) { return pos & (-pos);}int query(int pos) { int ans = 0; while(pos) { ans += c[pos]; pos -= lowbit(pos); } return ans;}void add(int pos) { while(pos <= a) { c[pos] ++; pos += lowbit(pos); }}int main( ) { freopen("fly.in", "r", stdin); freopen("fly.out", "w", stdout); scanf("%d%d%d%d",& n,& x,& a,& mod); long long rev = 0; int cur = x, idc = 0; for(int i = 1;i <= n;i ++) { if(cur >= a) { rev -= idc; if(cur < x) rev ++; ans += rev; } else rev = i - 1 - query(cur + 1), ans += rev, add(cur + 1); cur += a; if(cur >= mod) cur -= mod, idc ++; } printf("%lld\n", ans);}

转载于:https://www.cnblogs.com/Rubenisveryhandsome/p/9897507.html

你可能感兴趣的文章
关于mysql中GROUP_CONCAT函数的使用
查看>>
OD使用教程20 - 调试篇20
查看>>
Java虚拟机(JVM)默认字符集详解
查看>>
Java Servlet 过滤器与 springmvc 拦截器的区别?
查看>>
(tmp >> 8) & 0xff;
查看>>
linux命令之ifconfig详细解释
查看>>
NAT地址转换
查看>>
Nhibernate 过长的字符串报错 dehydration property
查看>>
Deque - leetcode 【双端队列】
查看>>
gulp插件gulp-ruby-sass和livereload插件
查看>>
免费的大数据学习资料,这一份就足够
查看>>
clientWidth、clientHeight、offsetWidth、offsetHeight以及scrollWidth、scrollHeight
查看>>
企业级应用与互联网应用的区别
查看>>
itext jsp页面打印
查看>>
Perl正则表达式匹配
查看>>
DB Change
查看>>
nginx --rhel6.5
查看>>
Eclipse Python插件 PyDev
查看>>
selenium+python3模拟键盘实现粘贴、复制
查看>>
第一篇博客
查看>>