老C的任务

题目大意:

维护一个二维平面,初始给出一些点及其权.多次询问某个矩形内的权和.

n,m <= 100000

题解:

签到题.

CDQ水一水.

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. typedef long long ll;
  6. inline void read(int &x){
  7. x=0;static char ch;static bool flag;flag = false;
  8. while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
  9. while(x=(x<<1)+(x<<3)+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
  10. }
  11. #define rg register int
  12. #define rep(i,a,b) for(rg i=(a);i<=(b);++i)
  13. #define per(i,a,b) for(rg i=(a);i>=(b);--i)
  14. const int maxn = 100010;
  15. const int maxm = maxn;
  16. struct Node{
  17. int x,y;
  18. int type,val,id;
  19. Node(){}
  20. Node(const int &a,const int &b,
  21. const int &c,const int &d,const int &e){
  22. x = a;y = b;type = c;val = d;id = e;
  23. }
  24. }q[maxn*6];
  25. #define lowbit(x) (x&-x)
  26. int n,m,mxlim;
  27. ll c[maxn*6];int vis[maxn*6],T;
  28. inline void modify(int x,ll d){
  29. for(;x <= mxlim;x += lowbit(x)){
  30. if(vis[x] == T) c[x] += d;
  31. else c[x] = d,vis[x] = T;
  32. }
  33. }
  34. inline ll query(int x){
  35. ll ret = 0;
  36. for(;x;x-=lowbit(x)) if(vis[x] == T) ret += c[x];
  37. return ret;
  38. }
  39. int qcnt = 0;ll ans[maxm];
  40. void solve(int l,int r){
  41. if(l == r) return ;
  42. int mid = l+r >> 1;
  43. solve(l,mid);solve(mid+1,r);
  44. ++ T;rg i = l,j = mid+1,k = l;
  45. static Node tmp[maxn*6];
  46. while(i <= mid || j <= r){
  47. if(i > mid || (j <= r && q[j].x < q[i].x)){
  48. if(q[j].type == 2){
  49. ans[q[j].id] += query(q[j].y)*q[j].val;
  50. }
  51. tmp[k++] = q[j++];
  52. }else{
  53. if(q[i].type == 1) modify(q[i].y,q[i].val);
  54. tmp[k++] = q[i++];
  55. }
  56. }
  57. rep(i,l,r) q[i] = tmp[i];
  58. return ;
  59. }
  60. struct num{
  61. int x,y,val;
  62. }p[maxn];
  63. struct number{
  64. int x1,y1,x2,y2;
  65. }nu[maxm];
  66. int b[maxn*6],cnt;
  67. int main(){
  68. read(n);read(m);
  69. rg x,y,v;
  70. rep(i,1,n){
  71. read(p[i].x);read(p[i].y);read(p[i].val);
  72. b[++cnt] = p[i].y;
  73. }
  74. rg xx,yy;
  75. rep(i,1,m){
  76. read(x);read(y);read(xx);read(yy);
  77. b[++cnt] = y;b[++cnt] = yy;
  78. if(x > xx) swap(x,xx);
  79. if(y > yy) swap(y,yy);
  80. nu[i].x1 = x;nu[i].y1 = y;
  81. nu[i].x2 = xx;nu[i].y2 = yy;
  82. }
  83. sort(b+1,b+cnt+1);
  84. rep(i,1,n){
  85. p[i].y = lower_bound(b+1,b+cnt+1,p[i].y) - b;
  86. x = p[i].x;y = p[i].y;v = p[i].val;
  87. q[++qcnt] = Node(x,y,1,v,0);
  88. }
  89. rep(i,1,m){
  90. y = lower_bound(b+1,b+cnt+1,nu[i].y1) - b;
  91. yy = lower_bound(b+1,b+cnt+1,nu[i].y2) - b;
  92. x = nu[i].x1;xx = nu[i].x2;
  93. q[++qcnt] = Node(xx,yy,2,1,i);
  94. q[++qcnt] = Node(x-1,yy,2,-1,i);
  95. q[++qcnt] = Node(xx,y-1,2,-1,i);
  96. q[++qcnt] = Node(x-1,y-1,2,1,i);
  97. }
  98. mxlim = cnt;
  99. solve(1,qcnt);
  100. rep(i,1,m){
  101. printf("%lld\n",ans[i]);
  102. }
  103. return 0;
  104. }

题目: 老 C 的方块

题目大意:

给定一个这样的R行C列网格图:加粗边称为特殊边



定义若出现下列情况本质相同的情况则不合法.



现在给定网格图内哪些格子是存在的及其被删除的代价共n个

最小化使得网格图合法的代价.

R,C,n <= 100000

题解:

观察所有不合法的状态.

我们发现其实就是特殊边两端不能都有大小超过2的四连块.(不经过特殊边)

所以我们可以列出一些关系:

如果将题目中给出的网格图的行列看成横纵坐标轴:(即(1,1)和(2,1)之间为特殊边)

我们可以得到这样的关系:

对于特殊边(3,2) - (4,2)来说.

如果要这条特殊边合法,那么必须是两边不能同时含有大小超过2的四连块.

那么如果我们删除(3,2)或者(4,2)这是一定满足的.

下面就是不删除(3,2)或者(4,2)的情况,那么我们知道:

要么全部删除(3,1),(2,2),(3,3),要么全部删除(4,1),(5,2),(4,3).

然后我们发现我们可以对网格图进行三色染色:建立最小割模型.

假设我们将(3,1),(2,2),(3,3)染成黑色那么(4,1),(5,2),(4,3)一定是白色.

然后将所有在特殊边两边的点染成黄色.

可以建立最小割模型:

蓝色边为删除对应格子的代价,黑色均为inf,黄色边为特殊边两边的各自的代价的最小值.

跑最小割即可.

  1. #include <map>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. using namespace std;
  6. typedef long long ll;
  7. inline void read(int &x){
  8. x=0;char ch;bool flag = false;
  9. while(ch=getchar(),ch<'!'); if(ch == '-') ch=getchar(),flag = true;
  10. while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
  11. }
  12. #define rg register int
  13. #define rep(i,a,b) for(rg i=(a);i<=(b);++i)
  14. #define per(i,a,b) for(rg i=(a);i>=(b);--i)
  15. typedef pair<int,int> pa;
  16. const int maxn = 100010;
  17. const int inf = 0x3f3f3f3f;
  18. struct Edge{
  19. int to,next,cap;
  20. }G[maxn*10];
  21. int head[maxn],cnt = 1;
  22. void add(int u,int v,int c){
  23. G[++cnt].to = v;
  24. G[cnt].next = head[u];
  25. head[u] = cnt;
  26. G[cnt].cap = c;
  27. }
  28. inline void insert(int u,int v,int c){
  29. add(u,v,c);add(v,u,0);
  30. }
  31. #define v G[i].to
  32. int dis[maxn],q[maxn],l,r,S,T;
  33. bool bfs(){
  34. memset(dis,-1,sizeof dis);
  35. l = 0;r = -1;q[++r] = S;
  36. dis[S] = 0;
  37. while(l <= r){
  38. int u = q[l++];
  39. for(int i = head[u];i;i=G[i].next){
  40. if(dis[v] == -1 && G[i].cap != 0){
  41. dis[v] = dis[u] + 1;
  42. q[++r] = v;
  43. }
  44. }
  45. }return dis[T] != -1;
  46. }
  47. int dfs(int u,int f){
  48. if(u == T || f == 0) return f;
  49. int ret = 0;
  50. for(int i = head[u];i;i=G[i].next){
  51. if(dis[v] == dis[u] + 1 && G[i].cap){
  52. int x = dfs(v,min(f,G[i].cap));
  53. f -= x;ret += x;
  54. G[i].cap -= x;
  55. G[i^1].cap += x;
  56. if(f == 0) break;
  57. }
  58. }return ret;
  59. }
  60. inline int dinic(){
  61. int ret = 0;
  62. while(bfs()) ret += dfs(S,inf);
  63. return ret;
  64. }
  65. #undef v
  66. inline bool ca(int x,int y){
  67. int id = (x + 1) >> 1;
  68. if(id & 1) return (y&1) == 1;
  69. else return (y & 1) == 0;
  70. }
  71. inline bool cb(int x,int y){
  72. int id = (x + 1) >> 1;
  73. if(id & 1){
  74. if((y & 1) == 1) return false;
  75. return (x & 1) == 1;
  76. }else{
  77. if((y & 1) == 0) return false;
  78. return (x & 1) == 0;
  79. }
  80. }
  81. inline bool cc(int x,int y){
  82. int id = (x + 1) >> 1;
  83. if(id & 1){
  84. if((y & 1) == 1) return false;
  85. return (x & 1) == 0;
  86. }else{
  87. if((y & 1) == 0) return false;
  88. return (x & 1) == 1;
  89. }
  90. }
  91. int d1[3][2] = {{-1,0},{0,1},{0,-1}};
  92. int d2[3][2] = {{1,0},{0,1},{0,-1}};
  93. map<pa,int>mp;
  94. struct Node{
  95. int x,y,w;
  96. }p[maxn];
  97. int main(){
  98. int C,R,n;read(C);read(R);read(n);
  99. S = maxn - 5;T = S + 1;
  100. rep(i,1,n){
  101. read(p[i].x);read(p[i].y);read(p[i].w);
  102. mp[make_pair(p[i].x,p[i].y)] = i;
  103. if(cb(p[i].x,p[i].y)) insert(S,i,p[i].w);
  104. if(cc(p[i].x,p[i].y)) insert(i,T,p[i].w);
  105. }
  106. rep(i,1,n){
  107. if( (p[i].x & 1) && ca(p[i].x,p[i].y)
  108. && (mp.count(make_pair(p[i].x+1,p[i].y)))){
  109. rg j = mp[make_pair(p[i].x+1,p[i].y)];
  110. if(p[i].y & 1){
  111. insert(i,j,min(p[i].w,p[j].w));
  112. rep(k,0,2){
  113. rg nx = p[i].x + d1[k][0];
  114. rg ny = p[i].y + d1[k][1];
  115. if(!mp.count(make_pair(nx,ny))) continue;
  116. insert(mp[make_pair(nx,ny)],i,inf);
  117. }
  118. rep(k,0,2){
  119. rg nx = p[j].x + d2[k][0];
  120. rg ny = p[j].y + d2[k][1];
  121. if(!mp.count(make_pair(nx,ny))) continue;
  122. insert(j,mp[make_pair(nx,ny)],inf);
  123. }
  124. }else{
  125. insert(j,i,min(p[i].w,p[j].w));
  126. rep(k,0,2){
  127. rg nx = p[i].x + d1[k][0];
  128. rg ny = p[i].y + d1[k][1];
  129. if(!mp.count(make_pair(nx,ny))) continue;
  130. insert(i,mp[make_pair(nx,ny)],inf);
  131. }
  132. rep(k,0,2){
  133. rg nx = p[j].x + d2[k][0];
  134. rg ny = p[j].y + d2[k][1];
  135. if(!mp.count(make_pair(nx,ny))) continue;
  136. insert(mp[make_pair(nx,ny)],j,inf);
  137. }
  138. }
  139. }
  140. }
  141. int ans = dinic();
  142. printf("%d\n",ans);
  143. return 0;
  144. }

老 C 的键盘

题目大意:

有一个n的排列对于每个位置i,给出[i/2]与i位置上的数的大小关系,求可能的排列数.

n <= 100

题解:

不难发现实际上这是一棵树.

我们把这棵树建出来,那么现在变成一给定一棵树,树上的边代表的父子的大小关系.

我们考虑树归 : 设\(f[i][j]\)表示在以i为根的子树内根作为排名为j的值出现的排列数.

那么问题就在于状态的合并更新了.

对于一个\(f[u][]\)要将儿子的状态\(f[v][]\)合并进来,我们首先分情况讨论:

  • u的值必须 > v的值:

    我们想象成两个排列进行合并.

    我们知道我们必须满足的条件即v在u的前面.

    那么我们枚举一下需要有多少排在u的前面即可.

    由于需要保证相对顺序不发生变化,所以将n个数插到m个数中的方案即:\(C_{n+m-1}^m\)

    但是由于这里要么前面能插,要么后面能插,即什么时候都多一个可以插的位置,

    所以实际上这里插入的方案数为\(C_{n+m}^m\)

    这样我们列出转移方程:

\[f[u][j+k] += C_{j-1+k}^{k}C_{s_u-j+s_v-k}^{s_v-k}*f[u][j]\sum_{i=1}^kf[v][i]
\]

  • u的值必须 < v的值:

    相应地列出方程:

\[f[u][j+k-1] += C_{j-1+k-1}^{k-1}C_{s_u-j+s_v-(k-1)}^{s_u-j}*f[u][j]\sum_{i=k}^nf[v][i]
\]

预处理前缀后缀和可以将sigma消掉.

据说这么做复杂度是\(O(n^2\log n)\)的..我也不知道为什么..

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. typedef long long ll;
  6. inline void read(int &x){
  7. x=0;static char ch;static bool flag;flag = false;
  8. while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
  9. while(x=(x<<1)+(x<<3)+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
  10. }
  11. #define rg register int
  12. #define rep(i,a,b) for(rg i=(a);i<=(b);++i)
  13. #define per(i,a,b) for(rg i=(a);i>=(b);--i)
  14. const int maxn = 128;
  15. const int mod = (1e9 + 7);
  16. struct Edge{
  17. int to,next,type;
  18. }G[maxn<<1];
  19. int head[maxn],cnt;
  20. void add(int u,int v,int d){
  21. G[++cnt].to = v;
  22. G[cnt].next = head[u];
  23. head[u] = cnt;
  24. G[cnt].type = d;
  25. }
  26. int C[maxn][maxn];
  27. inline void prework(int n){
  28. C[0][0] = 1;
  29. rep(i,1,n) rep(j,0,n){
  30. C[i][j] = C[i-1][j];
  31. if(j != 0) C[i][j] += C[i-1][j-1];
  32. if(C[i][j] >= mod) C[i][j] -= mod;
  33. }
  34. }
  35. int f[maxn][maxn],pre[maxn][maxn],suf[maxn][maxn];
  36. inline void init(){
  37. memset(head,0,sizeof head);
  38. cnt = 0;
  39. }
  40. int siz[maxn],n;
  41. #define v G[i].to
  42. void dfs(int u,int fa){
  43. siz[u] = 1;
  44. for(int i = head[u];i;i=G[i].next){
  45. if(v == fa) continue;
  46. dfs(v,u);siz[u] += siz[v];
  47. }
  48. rep(i,2,n) f[u][i] = 0;
  49. f[u][1] = 1;
  50. rg s = 1;
  51. static int g[maxn];
  52. for(int i = head[u];i;i=G[i].next){
  53. if(v == fa) continue;
  54. rep(j,1,s+siz[v]) g[j] = 0;
  55. if(G[i].type == -1){
  56. rep(j,1,s) rep(k,1,siz[v]){
  57. g[j+k-1] += 1LL*C[j+k-2][k-1]*C[s-j+siz[v]-k+1][s-j]%mod*f[u][j]%mod*suf[v][k]%mod;
  58. if(g[j+k-1] >= mod) g[j+k-1] -= mod;
  59. }
  60. }else{
  61. rep(j,1,s) rep(k,1,siz[v]){
  62. g[j+k] += 1LL*C[j+k-1][k]*C[s-j+siz[v]-k][s-j]%mod*f[u][j]%mod*pre[v][k]%mod;
  63. if(g[j+k] >= mod) g[j+k] -= mod;
  64. }
  65. }
  66. rep(j,1,s + siz[v]) f[u][j] = g[j];
  67. s += siz[v];
  68. }
  69. rep(i,1,n){
  70. pre[u][i] = pre[u][i-1] + f[u][i];
  71. if(pre[u][i] >= mod) pre[u][i] -= mod;
  72. }
  73. per(i,n,1){
  74. suf[u][i] = suf[u][i+1] + f[u][i];
  75. if(suf[u][i] >= mod) suf[u][i] -= mod;
  76. }
  77. return ;
  78. }
  79. #undef v
  80. inline void work(){
  81. init();read(n);
  82. rg u,v;char ch;
  83. rep(i,2,n){
  84. u = i>>1;
  85. while(ch=getchar(),ch<'!');
  86. v = i;
  87. if(ch == '<') add(u,v,-1),add(v,u,1);
  88. else add(u,v,1),add(v,u,-1);
  89. }
  90. dfs(1,1);
  91. int ans = 0;
  92. rep(i,1,n){
  93. ans += f[1][i];
  94. if(ans >= mod) ans -= mod;
  95. }
  96. printf("%d\n",ans);
  97. }
  98. int main(){
  99. int T;T = 1;
  100. prework(100);
  101. while(T--) work();
  102. return 0;
  103. }

bzoj 4822~4824 CQOI2017题解的更多相关文章

  1. BZOJ 1003 物流运输 题解 【SPFA+DP】

    BZOJ 1003 物流运输 题解 Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的 ...

  2. BZOJ 1191 超级英雄 Hero 题解

    BZOJ 1191 超级英雄 Hero 题解 Description 现在电视台有一种节目叫做超级英雄,大概的流程就是每位选手到台上回答主持人的几个问题,然后根据回答问题的多少获得不同数目的奖品或奖金 ...

  3. bzoj 4822: [Cqoi2017]老C的任务

    4822: [Cqoi2017]老C的任务 练手速... #include <iostream> #include <cstdio> #include <cstring& ...

  4. bzoj 4824: [Cqoi2017]老C的键盘

    Description 老 C 是个程序员.     作为一个优秀的程序员,老 C 拥有一个别具一格的键盘,据说这样可以大幅提升写程序的速度,还能让写出来的程序 在某种神奇力量的驱使之下跑得非常快.小 ...

  5. ●BZOJ 4822 [Cqoi2017]老C的任务

    题链: https://www.luogu.org/problemnew/show/P3755 (洛谷上数据范围给全了的) 题解: 树状数组,离线询问 (本来想弄一个二维树状数组/二维RMQ,然后直接 ...

  6. BZOJ 4824 [Cqoi2017]老C的键盘 ——树形DP

    每一个限制条件相当于一条有向边, 忽略边的方向,就成了一道裸的树形DP题 同BZOJ3167 唯一的区别就是这个$O(n^3)$能过 #include <map> #include < ...

  7. BZOJ 4822 [Cqoi2017]老C的任务 ——树状数组

    直接离散化之后用树状数组扫一遍. 把每一个询问拆成四个就可以做了. %Silvernebula 怒写KD-Tree #include <map> #include <cmath> ...

  8. bzoj 4824: [Cqoi2017]老C的键盘【树形dp】

    参考:https://www.cnblogs.com/FallDream/p/bzoj4824.html 画一画就会发现关系形成了一棵二叉树(其实看到n-1就能想到 然后dp,设f[i][j]为点i在 ...

  9. bzoj 4822: [Cqoi2017]老C的任务【扫描线+树状数组+二维差分】

    一个树状数组能解决的问题分要用树套树--还写错了我别是个傻子吧? 这种题还是挺多的,大概就是把每个矩形询问差分拆成四个点前缀和相加的形式(x1-1,y1-1,1)(x2.y2,1)(x1-1,y2,- ...

随机推荐

  1. poj 2524 Ubiquitous Religions(并查集)

    Ubiquitous Religions Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 23168   Accepted:  ...

  2. ArcGIS Scalebar 比例尺

    说明.这篇博文的示例代码 地图充满body arcgis api for javascript iis怎么离线部署 请参考我前面的博文 1.运行效果 3.HTML代码 <!DOCTYPE htm ...

  3. rm_invalid_file

    import xlrd import time import sys import os import requests import sqlite3 import threading curPath ...

  4. TextView属性

    TextView及其子类,当字符内容太长显示不下时可以省略号代替未显示的字符:省略号可以在显示区域的起始,中间,结束位置,或者以跑马灯的方式显示文字(textview的状态为被选中). 其实现只需在x ...

  5. shell编程3 ---流程控制语句

    shell编程流程控制语句 一.if流程控制语句 1.单分支if条件判断语句 if [  条件判断式 ]:then     或者   if[ 条件判断式 ] 程序                   ...

  6. TCP标准模板

    伪代码 #创建一个TCP服务器 ss = socket() #创建服务器套接字 ss.bind() #把地址绑定到套接字上 ss.listen() #监听连接 inf_loop: #服务器无线循环 c ...

  7. eclipse新建Maven项目

    1.在eclipse中安装maven插件 2.点击File->new->maven project,出现弹窗后点击next. 接着在弹窗Select an Archetype中,filte ...

  8. vmware虚拟机安装MAC OSX10.10Yosemite简要记录

    vmware所在环境为win7 64位系统,intel4核CPU,16G内存. 本人安装的是OSX10.10Yosemite的CDR镜像. 1. 在服务中停止所有vmware服务. 2. 安装unlo ...

  9. java网络爬虫爬虫小栗子

    简要介绍: 使用java开发的爬虫小栗子,存储到由zookeeper协调的hbase中 主要过程是模拟Post请求和get请求,html解析,hbase存储 源码:https://github.com ...

  10. grep egrep

    grep: Global search REgular expression and Print out the line. 作用: 文本搜索工具,根据用户指定的“模式”对目标文本逐行进行匹配检查:打 ...