A:

题目大意:

在一个multiset中要求支持3种操作:

1.增加一个数

2.删去一个数

3.给出一个01序列,问multiset中有多少这样的数,把它的十进制表示中的奇数改成1,偶数改成0后和给出的01序列相等(比较时如果长度不等各自用0补齐)

题解:

1.我的做法是用Trie数来存储,先将所有数用0补齐成长度为18位,然后就是Trie的操作了。

2.官方题解中更好的做法是,直接将每个数的十进制表示中的奇数改成1,偶数改成0,比如12345,然后把它看成二进制数10101,还原成十进制是21,然后cnt[21]++,求答案的时候只要把01序列看成二进制数,然后转换成十进制x,cnt[x]就是答案。

我的代码(Trie做法)

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cstdlib>
#include <set>
using namespace std; #define X first
#define Y second
#define N 1000010
typedef long long ll;
typedef pair<int,int> pii; int n,tot=;
int cnt[N],ch[N][]; void Add(int x,ll val,int k,int op)
{
cnt[x]+=op;
if (k==) return;
int v=(val%)&;
if (!ch[x][v]) ch[x][v]=++tot;
Add(ch[x][v],val/,k-,op);
} int Query(int x,ll val,int k)
{
if (k==) return cnt[x];
int v=(val%)&;
if (!ch[x][v]) return ;
return Query(ch[x][v],val/,k-);
} int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout); scanf("%d",&n);
char op; ll x;
for (int i=;i<=n;i++)
{
scanf(" %c%I64d",&op,&x);
if (op=='+') Add(,x,,);
if (op=='-') Add(,x,,-);
if (op=='?') printf("%d\n",Query(,x,));
}
return ;
}

B:

题目大意:

在一个n*n的矩形中,有2个没有公共边也不重叠的矩形,然后最多可以询问200次,每次询问一个矩形中有多少个矩形(会给出答案0或1或2),要求找到这两个矩形的位置。

题解:

1.如果只有一个矩形,显然可以用二分确定它的坐标。所以基本思想是找到一条分界线 将这两个矩形分开,然后各自独立寻找位置。

2.对于这两个矩形,要么是左右关系,要么是上下关系。如果是左右关系,我们先确定询问的左边界,上边界和下边界,然后逐步增大右边界,那么矩形的个数肯定是从0到1到2递增的,所以可以二分出这个 分界线。 上下关系同理。 具体实现看代码。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cstdlib>
#include <set>
using namespace std; #define X first
#define Y second
#define Mod 1000000007
#define N 100010
typedef long long ll;
typedef pair<int,int> pii; int xx1,yy1,xx2,yy2,X1,Y1,X2,Y2; int Check(int x1,int y1,int x2,int y2)
{
printf("? %d %d %d %d\n",x1,y1,x2,y2);
fflush(stdout);
int x; scanf("%d",&x);
return x;
} void Solve(int l,int d,int r,int u)
{
int L,R,Mid,x1,y1,x2,y2; L=d,R=u;
while (L<R)
{
Mid=(L+R)>>;
if (Check(l,d,r,Mid)==) L=Mid+;
else R=Mid;
}
y2=L; L=d,R=u;
while (L<R)
{
Mid=(L+R+)>>;
if (Check(l,Mid,r,u)==) R=Mid-;
else L=Mid;
}
y1=L; L=l,R=r;
while (L<R)
{
Mid=(L+R)>>;
if (Check(l,d,Mid,u)==) L=Mid+;
else R=Mid;
}
x2=L; L=l,R=r;
while (L<R)
{
Mid=(L+R+)>>;
if (Check(Mid,d,r,u)==) R=Mid-;
else L=Mid;
}
x1=L; if (!xx1) xx1=x1,yy1=y1,xx2=x2,yy2=y2;
else X1=x1,Y1=y1,X2=x2,Y2=y2;
} int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout); int n,L,R,Mid;
scanf("%d",&n); L=,R=n;
while (L<R)
{
Mid=(L+R)>>;
if (Check(,,Mid,n)>=) R=Mid;
else L=Mid+;
} if (Check(,,L,n)== && Check(L+,,n,n)==)
{
Solve(,,L,n);
Solve(L+,,n,n);
}
else
{
L=,R=n;
while (L<R)
{
Mid=(L+R)>>;
if (Check(,,n,Mid)>=) R=Mid;
else L=Mid+;
}
Solve(,,n,L);
Solve(,L+,n,n);
}
printf("! %d %d %d %d %d %d %d %d\n",xx1,yy1,xx2,yy2,X1,Y1,X2,Y2);
fflush(stdout); return ;
}

C:

题目大意:

给出一个长度为n的数列(n<=3000),每次操作可以把其中一个数增大1或者减小1,求最少操作次数使得数列单调增。

题解:

1.首先一个转化:   $a_i<a_{i+1}  <--> a_i-i<=a_{i+1}-(i+1)$  所以把所有$a_i$减去$i$就转化为单调不减,就和POJ3666一样了。

具体可以看 http://www.cnblogs.com/vb4896/p/5877962.html    时间复杂度O(n2)

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cstdlib>
#include <set>
using namespace std; #define X first
#define Y second
#define Mod 1000000007
#define N 3010
typedef long long ll;
typedef pair<int,int> pii; inline int Mul(int x,int y){return 1ll*x*y%Mod;}
inline int Add(int x,int y){return ((x+y)%Mod+Mod)%Mod;} int n,m;
int a[N],b[N];
ll dp[N][N],Ans=1ll<<; void Solve()
{
for (int j=;j<=m;j++) dp[][j]=abs(b[j]-a[]);
for (int i=;i<=n;i++)
{
ll tmp=1ll<<;
for (int j=;j<=m;j++)
{
tmp=min(tmp,dp[i-][j]);
dp[i][j]=abs(b[j]-a[i]);
dp[i][j]+=tmp; }
}
for (int j=;j<=m;j++) Ans=min(Ans,dp[n][j]);
} int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout); scanf("%d",&n);
for (int i=;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i]=a[i]-i;
sort(b+,b+n+);
for (int i=;i<=n;i++) if (i== || b[i]!=b[i-]) b[++m]=b[i]; Solve();
printf("%I64d\n",Ans); return ;
}

2.其实这题还有个O(nlogn做法)

以下是在 评论区看到的:为了便于理解 我修改了下,加了点注释。

There is a very short (10 lines!) and fast O(nlgn) solution for Div1C, proposed by woqja125 :

Start by subtracting i from all A[i]. We'll define fi(X) = Minimum operation to make A[1 .. i] monotonically increasing, while keeping A[i] <= X. it's easy to see that the recurrence is —

  • Min{|Ai — Y| } (Y <= X)       if i == 1
  • Min{fi-1(Y) + |Ai — Y|} (Y<=X)    otherwise.

Observation : fi is an unimodal function, which have a nonpositive integer slopes. Denote Opt(i) as a point X which makes fi(X) minimum.

We will maintain those functions and calculate the minimum. we examine two cases :

(Fi(X)的图像可以看成是Fi-1(X)和 |Ai — Y|这两个图像的叠加。 Fi(X)的图像总是斜率小于0且斜率绝对值递减的曲线,并且从Opt(i)开始变成水平)

Case 1 : Opt(i-1) <= A[i]. In this case, Opt(i) = A[i], and every point under A[i] have +1 slope.

Case 2 : Opt(i-1) > A[i]. This case is tricky. every point over A[i] have +1 slope, and every point under A[i] have -1 slope. Opt(i) is the point where slope of fi is changed into -1 -> 0. When observing the function, Fi(Opt(i)) = F(i-1)(Opt(i-1)) + Opt(i-1) — A[i].

为了求答案,只要维护好这个Fi(X)曲线就好。具体实现的时候,由于从Fi-1到Fi只和Opt(i-1)有关,我们用个大根堆保存好每一个斜率开始改变的点,然后每次取出最大的点就是

Opt(i-1).  具体实现看代码:

///By woqja125, contest: Codeforces Round #371 (Div. 1), problem: (C) Sonya and Problem Wihtout a Legend, Accepted, #

#include<stdio.h>
#include<queue> int main()
{
int n, t;
long long ans = ;
std::priority_queue<int> Q;
scanf("%d%d", &n, &t);
Q.push(t);
for(int i=; i<n; i++)
{
scanf("%d", &t); t-=i;
Q.push(t); //Ai>=Opt(i-1)的时候仅仅增加了Ai这个转折点
if(Q.top() > t) //Ai<Opt(i-1)的时候
{
ans += Q.top() - t;
Q.pop();
Q.push(t); //t push了2次,为的是使得任意相邻的两点之间斜率相差1,即使两点可能重合
}
}
printf("%lld", ans);
return ;
}

D:

题目大意:

给出n*m的01矩阵,最多1e6个询问,每次询问一个子矩形中最大的全1正方形的边长。

题解

1.首先可以dp出以(i,j)为左下角的最大正方形边长,dp[i][j]=max{dp[i+1][j+1],dp[i+1][j],dp[i][j+1]}+1.当然如果(i,j)格是0 那dp[i][j]=0.

2.考虑二分答案。二分时检查矩形(x1,y1)-(x2-Mid+1,y2-Mid+1)里的dp值是否有大于等于Mid的。  区间的最大值可以用二维RMQ解决...第一次写,竟然写对了。然后想起前几天学了个用树状数组求区间最大值的方法,就想把它也扩展到二维,写到一半发现剧难写,再加上这几天心不是很静,弃疗了。

还是贴个RMQ的代码吧。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cstdlib>
#include <set>
using namespace std; #define X first
#define Y second
#define Mod 1000000007
#define N 1010
#define Inf 1000000007
typedef long long ll;
typedef pair<int,int> pii; int n,m,Q;
int v[N][N],dp[N][N],sum[N][N];
int f[N][N][][]; void Build()
{
for (int p=,l1=;l1<=n;l1<<=,p++)
{
for (int q=,l2=;l2<=m;l2<<=,q++)
{
if (p+q==) continue;
for (int i=;i+l1-<=n;i++)
{
for (int j=;j+l2-<=m;j++)
{
if (p!=) f[i][j][p][q]=max(f[i][j][p-][q],f[i+(l1>>)][j][p-][q]);
else f[i][j][p][q]=max(f[i][j][p][q-],f[i][j+(l2>>)][p][q-]);
}
}
}
}
} int Getmax(int x1,int y1,int x2,int y2)
{
int p=,l1=,q=,l2=,tmp1,tmp2;
while (l1<=x2-x1+) l1<<=,p++; p--,l1>>=;
while (l2<=y2-y1+) l2<<=,q++; q--,l2>>=; tmp1=max(f[x1][y1][p][q],f[x1][y2-l2+][p][q]);
tmp2=max(f[x2-l1+][y1][p][q],f[x2-l1+][y2-l2+][p][q]);
return max(tmp1,tmp2);
} int main()
{
//freopen("in.in","r",stdin);
//freopen("out.out","w",stdout); scanf("%d%d",&n,&m);
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
{
scanf("%d",&v[i][j]);
sum[i][j]=sum[i][j-]+sum[i-][j]-sum[i-][j-]+v[i][j];
}
for (int i=n;i>=;i--)
{
for (int j=m;j>=;j--)
{
if (v[i][j]==) dp[i][j]=;
else dp[i][j]=min(min(dp[i+][j+],dp[i][j+]),dp[i+][j])+;
f[i][j][][]=dp[i][j];
}
} Build();
int L,R,Mid,x1,y1,x2,y2;
scanf("%d",&Q);
while (Q--)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if (sum[x2][y2]-sum[x1-][y2]-sum[x2][y1-]+sum[x1-][y1-]==) printf("0\n");
else
{
L=,R=min(x2-x1+,y2-y1+);
while (L<R)
{
Mid=(L+R+)>>;
if (Getmax(x1,y1,x2-Mid+,y2-Mid+)>=Mid) L=Mid;
else R=Mid-;
}
printf("%d\n",L);
}
} return ;
}

Codeforces Round #371 (Div. 1)的更多相关文章

  1. Codeforces Round #371 (Div. 2)B. Filya and Homework

    题目链接:http://codeforces.com/problemset/problem/714/B 题目大意: 第一行输入一个n,第二行输入n个数,求是否能找出一个数x,使得n个数中的部分数加上x ...

  2. Codeforces Round #371 (Div. 2) - B

    题目链接:http://codeforces.com/contest/714/problem/B 题意:给定一个长度为N的初始序列,然后问是否能找到一个值x,然后使得序列的每个元素+x/-x/不变,最 ...

  3. Codeforces Round #371 (Div. 2) - A

    题目链接:http://codeforces.com/contest/714/problem/A 题意:有两个人A,B 给定A的时间区间[L1,R1], B的时间区间[L2,R2],然后在正好K分钟的 ...

  4. 严格递增类的dp Codeforces Round #371 (Div. 1) C dp

    http://codeforces.com/contest/713 题目大意:给你一个长度为n的数组,每次有+1和-1操作,在该操作下把该数组变成严格递增所需要的最小修改值是多少 思路:遇到这类题型, ...

  5. Codeforces Round #371 (Div. 2) C 大模拟

    http://codeforces.com/contest/714/problem/C 题目大意:有t个询问,每个询问有三种操作 ①加入一个数值为a[i]的数字 ②消除一个数值为a[i]的数字 ③给一 ...

  6. Codeforces Round #371 (Div. 1) C. Sonya and Problem Wihtout a Legend 贪心

    C. Sonya and Problem Wihtout a Legend 题目连接: http://codeforces.com/contest/713/problem/C Description ...

  7. Codeforces Round #371 (Div. 1) D. Animals and Puzzle 二维倍增

    D. Animals and Puzzle 题目连接: http://codeforces.com/contest/713/problem/D Description Owl Sonya gave a ...

  8. Codeforces Round #371 (Div. 2) C. Sonya and Queries 水题

    C. Sonya and Queries 题目连接: http://codeforces.com/contest/714/problem/C Description Today Sonya learn ...

  9. Codeforces Round #371 (Div. 2) D. Searching Rectangles 交互题 二分

    D. Searching Rectangles 题目连接: http://codeforces.com/contest/714/problem/D Description Filya just lea ...

随机推荐

  1. reactive-turtle

    reactive-turtle 标签(空格分隔): Scala Github 偶然在Github上看到一个有意思的小项目,一个粑粑教11岁的儿子学习scala,因为学习语法等太枯燥了,所以写了一个海龟 ...

  2. Download Oracle Forms 6i

    To download Oracle Forms Developer 6i from Oracle click this link http://download.oracle.com/otn/nt/ ...

  3. 企业办公3D指纹考勤系统解决方案(一)

    员工准时.正常出勤是企业考勤制度的基本要求,然而目前签名式.卡钟式.IC卡考勤系统均存在代打卡.人情卡.不易统计等漏洞,而市面上的光学指纹考勤机存在识别能力差.识别速度慢.使用寿命短.不能完全杜绝指纹 ...

  4. OpenCV2+入门系列(二):图像的打开、创建与显示(命令行)

    前置知识:数字图像的简略知识 这里只是最基础的知识,上课如果稍微听了课的同学可以直接略过不不看. 彩色图像: 对于一副数字图像,对于一副RGB色彩空间的彩色数字图像,它一共有宽X高个像素格子,每个格子 ...

  5. Sublime Text 3 支持的热门插件推荐(转载)

    SublimeText是一款非常精巧的文本编辑器,适合编写代码.做笔记.写文章.它用户界面十分整洁,功能非同凡响,性能快得出奇.这些非常棒的特性 包括任意跳转(Goto Anything).多重选择( ...

  6. 专为控制打印设计的CSS样式

    大多数Web设计师对打印控制还不是很熟悉,他们往往更迷恋像素,而不是打印机.在现实世界中,很多人依赖从网站上打印网页来参考: 在这个数字时代, 在一些特殊的场合,很多人手中还会拿着纸张.Web开发人员 ...

  7. Angular 2.0 的设计方法和原则

    转载自:Angular 2.0 的设计方法和原则 在开始实现Angular 2.0版本之际,我们认为应该着手写一些东西,告诉大家我们在设计上的考虑,以及为什么做这样的改变.现在把这些和大家一起分享,从 ...

  8. spring-task

    cronExpression的配置说明,具体使用以及参数请百度google 字段   允许值   允许的特殊字符 秒    0-59    , - * / 分    0-59    , - * / 小 ...

  9. Asp.Net_<%%>模式常用语法

    1.//弹出对话框.点击转向指定页面 Response.Write("<script>window.alert('该会员没有提交申请,请重新提交!')</script> ...

  10. grunt不是内部或外部命令错误处理

    如题, npm install -g grunt-cli发现grunt命令却不可用, 其实是环境变量问题,但是网上很多给出的方法其实是不准确的, 正确方法,可以通过npm root -g查看路径,之后 ...