ZOJ 4082 Little Sub and his Geometry Problem题解
题意
f(u,v):x小于等于u且y小于等于v的点才对f有贡献,每个这样的点贡献(u-x)+()
思路
=f(u_2,v_2)" class="mathcode" src="https://private.codecogs.com/gif.latex?u_1%20%5Cge%20u_2%20%5C%3B%20and%20%5C%3B%20v_1%20%5Cge%20v_2%20%5Cquad%20%5CRightarrow%20%5Cquad%20f%28u_1%2Cv_1%29%3E%3Df%28u_2%2Cv_2%29">
且等号当且仅当时取。
因此对于输入的0)" class="mathcode" src="https://private.codecogs.com/gif.latex?C%28C%3E0%29">,对于1个特定的
,至多有一个
似的
. (标号①)
当我们固定一个变量的时候,关于另一个变量是单调的。 (标号②)
因此,我选择横竖两条线移动。
初始状态u=0,v=N.此时f值显然过小。
对于一个状态,
如果f过小,则只能往竖线右调,f才可能增大。
如果f过大,则只能横线往下调。
如果f刚好,答案计数加1,同时,这个u已经不可能有v符合了。往右调(其实往下调也行,关键是要固定一种走法)。
f过小时,v往上调是没有意义的,因为初始状态是v所能取的最大值(N),能到达目前的状态,是从前面的太大或者已经计数过的答案状态转移过来的。往上调就是是走回头路,回去要不就是f过大,要不就是已经计数了的恰好等于f的状态。
同理,f过大时,竖线左调是没有意义的。
同时根据(标号①)的结论易证,不会有情况疏漏掉。
换句话说,如此移动,不重不漏,至多移动2N次。
具体可以参考C++源码
注意,getCount不要用二分,直接枚举就好了。
二分反而会更慢,慢原因是二分需要先排序,排序是,
是排序数组片段长度。
而注意到getCount(u,v)每一个u至多查询1次,直接枚举是,反而复杂度更低。
复杂度估计,由于每个片段至多查询一次,且最坏情况下所有片段都查询了。因此对于一个输入C,总的复杂度是.
有个2倍是因为对反过来的rp也要考虑。
因此总复杂度是
不考虑系数,大概带入数字算一下。不超过20*10*10^5+(1000-20)*10*10^4=1.18*10^8.
4s时间限制是OK的。
源码
java(Tle)
java一开始我的java jdk时1.8.ZOJ评测时1.7.莫名RE
后来用1.7,还是莫名RE.
最后故意加死循环,提交。二分测试发现ZOJ Java switch不支持枚举型变量。黑人问号。
最后无奈改成if语句,然后从Re变成Tle了。根据网上的进行了输入输出优化还是不行。
import java.util.*;
import java.io.*;
public class Main {
static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
public static void main(String[] args) {
try {
cin.nextToken();
int cnt = (int) cin.nval;
LittleSubAndHisGeometryProblem p;
for (int i = 0;i < cnt; ++i) {
p = new LittleSubAndHisGeometryProblem();
p.run();
}
cout.flush();
} catch (Exception e) {
}
}
}
class LittleSubAndHisGeometryProblem{
final int N;
int pointCnt;
PointsSys normal;
PointsSys reverse;
int queryCnt;
LittleSubAndHisGeometryProblem() throws Exception {
Main.cin.nextToken();
N = (int)Main.cin.nval;
Main.cin.nextToken();
pointCnt = (int)Main.cin.nval;
// 做准备工作,方便满足“a=a0,b<=b0的点的个数及他们的b之和”
normal = new PointsSys();
reverse = new PointsSys();
int x,y;
for (int i = 0;i < pointCnt; ++i) {
Main.cin.nextToken();
x = (int)Main.cin.nval;
Main.cin.nextToken();
y = (int)Main.cin.nval;
normal.add(x,y);
reverse.add(y,x);
}
Main.cin.nextToken();
queryCnt = (int)Main.cin.nval;
}
class PointSysQueryInfo{
int cnt = 0;
long sum = 0;
void add(long a) {
++cnt;
sum += a;
}
}
class PointsSys{
int cnt;
ArrayList<ArrayList<Integer>> p;
PointsSys() {
p = new ArrayList<ArrayList<Integer>>();
for (int i = 0;i <= N; ++i)
p.add(new ArrayList<Integer>());
}
void add(int x,int y) {
p.get(x).add(y);
}
void query(int x,int y,PointSysQueryInfo change) {
// 返回X值恰好为x,且Y值小于等于y的所有点的信息
// 返回点数和sigama(y-Yi) Yi取遍所有的满足要求的点的Y
change.cnt = 0;
change.sum = 0;
ArrayList<Integer> list = p.get(x);
for (int Y : list)
if (Y <= y)
change.add(y-Y);
}
}
public enum Move{
Right,Down
}
void count() {
// 求解符合题意的方案数
queryAns = 0;
if (2L*N*pointCnt <= c)
return;
int u = 0;
int v = N;
PointSysQueryInfo curr = new PointSysQueryInfo();
PointSysQueryInfo change = new PointSysQueryInfo();
Move moveFlag = Move.Right;
//boolean first = true;
while (u <= N && v > 0) {
if (curr.sum == c)
++queryAns;
if (moveFlag == Move.Right) { // Go Right
++u;
if (u > N) return;
normal.query(u, v ,change);
curr.sum += change.sum + curr.cnt;
curr.cnt += change.cnt;
} else { // Go Down
if (v <= 0) return;
reverse.query(v,u,change);
--v;
curr.cnt -= change.cnt;
curr.sum -= change.sum+curr.cnt;
}
if (curr.sum >= c)
moveFlag = Move.Down;
else
moveFlag = Move.Right;
}
return;
}
long c;
int queryAns;
void run() throws Exception {
boolean first = true;
for (int i = 0; i < queryCnt; ++i) {
Main.cin.nextToken();
c = (long)Main.cin.nval;
count();
if (first) {
Main.cout.print(queryAns);
first = false;
} else {
Main.cout.print(" "+queryAns);
}
}
Main.cout.println();
}
}
C++ (AC)
#include <bits/stdc++.h>
using namespace std;
const int kMaxN = 100005;
int N,K;
vector<int>p[kMaxN];
vector<int>rp[kMaxN];
void getCount(vector<int>&p,int b,int &cnt,long long &s) {
cnt = 0;
s = 0;
for (auto y : p)
if (y <= b) {
++cnt;
s += b-y;
}
}
int count(long long c) {
if (c >= 2ll*(long long)N*(long long)K)
return 0;
int u = 0;
int v = N;
int ans = 0;
bool isGoRight = true;
long long f,f0;
int cnt,cnt0;
f = 0; cnt = 0;
while (u <= N && v >= 1) {
if (f == c)
++ans;
if (isGoRight) { // Go Right
++u;
getCount(p[u],v,cnt0,f0);
f += f0+(long long)cnt;
cnt += cnt0;
} else { // Go Down
getCount(rp[v],u,cnt0,f0);
--v;
cnt -= cnt0;
f -= f0+(long long)cnt;
}
isGoRight = f < c;
}
return ans;
}
void work() {
cin>>N>>K;
for (int i = 0; i <= N; ++i) {
p[i].clear();
rp[i].clear();
}
int x,y;
for (int i = 0;i < K; ++i) {
cin>>x>>y;
p[x].push_back(y);
rp[y].push_back(x);
}
int Q;
cin>>Q;
long long c;
int ans;
for (int i = 0; i < Q; ++i) {
cin>>c;
ans = count(c);
if (i)
cout<<' '<<ans;
else
cout<<ans;
}
cout<<'\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while (T--)
work();
return 0;
}
ZOJ 4082 Little Sub and his Geometry Problem题解的更多相关文章
- ZOJ - 4082:Little Sub and his Geometry Problem (双指针)
Little Sub loves math very much, and has just come up with an interesting problem when he is working ...
- ZOJ Monthly, January 2019 Little Sub and his Geometry Problem 【推导 + 双指针】
传送门:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5861 Little Sub and his Geometry Prob ...
- HDU1086You can Solve a Geometry Problem too(判断线段相交)
You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/3 ...
- codeforces 361 E - Mike and Geometry Problem
原题: Description Mike wants to prepare for IMO but he doesn't know geometry, so his teacher gave him ...
- hdu 1086 You can Solve a Geometry Problem too
You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/3 ...
- CodeForces 689E Mike and Geometry Problem (离散化+组合数)
Mike and Geometry Problem 题目链接: http://acm.hust.edu.cn/vjudge/contest/121333#problem/I Description M ...
- Codeforces Gym 100338B Geometry Problem 计算几何
Problem B. Geometry ProblemTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudg ...
- you can Solve a Geometry Problem too(hdoj1086)
Problem Description Many geometry(几何)problems were designed in the ACM/ICPC. And now, I also prepare ...
- (hdu step 7.1.2)You can Solve a Geometry Problem too(乞讨n条线段,相交两者之间的段数)
称号: You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/ ...
随机推荐
- Java基于过滤器进行重定向不成功问题的兩種解決辦法,以及基於JSF的ajax重定向解決辦法
我创建了一个过滤器,只要用户没有登陆就不能连接到主界面,但是在doFilter方法中用重定向在前端跳转页面不成功. 原因:由于我的登陆界面是基于ajax请求的,而ajax默认不支持重定向,他只能局部更 ...
- THINKPHP-RCE-POC
thinkphp-RCE-POC 官方公告: 1.https://blog.thinkphp.cn/869075 2.https://blog.thinkphp.cn/910675 POC: thin ...
- KVM管理工具webvirtmgr的使用
WebVirtMgr的日常配置:添加宿主机,创建虚拟机,磁盘扩容,快照等具体操作记录如下: 一.创建虚拟机 1.创建存储池 点击创建的宿主机,进入虚拟机部署界面 点击“存储池”按钮,创建存储池(即创建 ...
- 如何在SQL Server中生成和使用CRUD存储过程
在本文中,请参阅如何在SQL Server中生成和使用CRUD存储过程. 大多数数据库系统基于缩写CRUD调用的最简单的4种数据操作操作进行操作. 此首字母缩写词代表CREATE,READ,UPDAT ...
- C# 获取鼠标在屏幕上的位置
获取鼠标位置及鼠标单击了哪个按键.private void GetMousePoint() { Point ms = Control.MousePosition; this.label ...
- java设计模式学习笔记——里氏替换原则
oo中的继承性的思考和说明 1.继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些七月,但是如果子类对这些已经实现的方法任意修改,就会对 ...
- JavaScript中基本数据类型之间的转换
在JavaScript中共有六种数据类型,其中有五种是基本数据类型,还有一种则是引用数据类型.五种基本数据类型分别是:Number 数值类型.String 字符串类型.Boolean 布尔类型, nu ...
- MySQL锁与事务隔离级别
一.概述 1.锁的定义 锁是计算机协调多个进程或线程并发访问某一资源的机制. 在数据库中,除了传统的计算资源(如CPU.RAM.IO等)的争用以外,数据也是一种供需要用户共享的资源.如何保证数据并发访 ...
- Policy-based Approach(基于策略的方法)
step 1:Neural Network as Actor step 2:goodness of function(训练一些Actor) 是一个序列,包含T个状态s.行为a.奖励s.代表某一次的开始 ...
- vue更改数组中的值
根据下标更改时 vm为新建的vue对象 ind为数组 第一个e为在数组ind中e索引位置 第二个e为更改为值e vm.$set(vm.ind,e,e) 常规更改 arr为数组 //添加 arr.pus ...