Postal Vans

题目大意

4*n的网格,要经过所有点的有向有环,不重复经过点的路径总数

n<=1000

题解

显然 插头dp

以4为切面

问题是,会发现 超精度

解决呢要么实现高精度,要么换python XD

c++实现 未+高精度,会爆掉

#include <bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--) using namespace std; const string filename = "vans"; void usefile(){
freopen((filename+".in").c_str(),"r",stdin);
freopen((filename+".out").c_str(),"w",stdout);
} int n; const int S1001 = 0;
const int S1122 = 1;
const int S1100 = 2;
const int S0110 = 3;
const int S0011 = 4;
const int S1221 = 5;
const int S0000 = 6; long long dp[1010][10];
int s2[10][10]; void init(){
s2[S1001][S0000] = 1;
s2[S1001][S1100] = 1;
s2[S1001][S0110] = 1;
s2[S1001][S0011] = 1;
s2[S1001][S1221] = 1; s2[S1122][S1001] = 1;
s2[S1122][S1122] = 1;
// s2[S1122][S1100] = 1; 不应该自闭
// s2[S1122][S0011] = 1; 不应该自闭
// s2[S1122][S0000] = 1; 不应该自闭 s2[S1100][S1122] = 1;
s2[S1100][S1001] = 1; s2[S0110][S1001] = 1; s2[S0011][S1122] = 1;
s2[S0011][S1001] = 1; // s2[S1221][S1001] = 1; 不应该自闭
s2[S1221][S0000] = 1;
s2[S1221][S1100] = 1;
s2[S1221][S0011] = 1;
s2[S1221][S1221] = 1;
} int main(){
usefile();
init();
cin>>n; dp[0][S1001] = 1;
dp[0][S1122] = 1;
rep(i,1,n){
rep(stateS,0,6){
rep(stateE,0,7){
if(s2[stateS][stateE]){
dp[i][stateE]+=dp[i-1][stateS];
}
}
}
}
// rep(i,0,n){
// rep(state,0,7){
// cout<<dp[i][state]<<"\t";
// }
// cout<<endl;
// }
cout<<dp[n-1][S0000]*2<<endl;
return 0;
}

增加高精度

#include <bits/stdc++.h>
typedef long long ll;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back using namespace std; const string filename = "vans"; void usefile(){
freopen((filename+".in").c_str(),"r",stdin);
freopen((filename+".out").c_str(),"w",stdout);
} class hpa{
int DIGITS = 100'000'000; // 08lld
vector<ll>vals;
public:
hpa(){
}
hpa(ll v){
vals.pb(v);
}
void print(){
if(vals.size() == 0){
printf("0");
return;
}
printf("%lld",vals[vals.size()-1]);
per(i,0,vals.size()-1){
printf("%08lld",vals[i]);
}
}
hpa operator +(const hpa &another) const {
hpa ret;
rep(i,0,vals.size()){
ret.vals.pb(vals[i]);
}
rep(i,0,another.vals.size()){
if(i >= ret.vals.size()){
ret.vals.pb(another.vals[i]);
}else{
ret.vals[i]+=another.vals[i];
if(ret.vals[i] >= DIGITS){
if(i == ret.vals.size()-1){
ret.vals.pb(0);
}
ret.vals[i+1]+=ret.vals[i]/DIGITS;
ret.vals[i]%=DIGITS;
}
}
}
return ret;
}
}; int n; const int S1001 = 0;
const int S1122 = 1;
const int S1100 = 2;
const int S0110 = 3;
const int S0011 = 4;
const int S1221 = 5;
const int S0000 = 6; hpa dp[1010][10];
int s2[10][10]; void init(){
s2[S1001][S0000] = 1;
s2[S1001][S1100] = 1;
s2[S1001][S0110] = 1;
s2[S1001][S0011] = 1;
s2[S1001][S1221] = 1; s2[S1122][S1001] = 1;
s2[S1122][S1122] = 1;
// s2[S1122][S1100] = 1; 不应该自闭
// s2[S1122][S0011] = 1; 不应该自闭
// s2[S1122][S0000] = 1; 不应该自闭 s2[S1100][S1122] = 1;
s2[S1100][S1001] = 1; s2[S0110][S1001] = 1; s2[S0011][S1122] = 1;
s2[S0011][S1001] = 1; // s2[S1221][S1001] = 1; 不应该自闭
s2[S1221][S0000] = 1;
s2[S1221][S1100] = 1;
s2[S1221][S0011] = 1;
s2[S1221][S1221] = 1;
} int main(){
usefile();
init();
cin>>n; dp[0][S1001] = 2;
dp[0][S1122] = 2;
rep(i,1,n){
rep(stateS,0,6){
rep(stateE,0,7){
if(s2[stateS][stateE]){
dp[i][stateE]=(dp[i][stateE]+dp[i-1][stateS]);
}
}
}
}
// rep(i,0,n){
// rep(state,0,7){
// cout<<dp[i][state]<<"\t";
// }
// cout<<endl;
// }
dp[n-1][S0000].print();
printf("\n");
return 0;
}

A Rectangular Barn

Mircea Pasoi -- 2003

题目大意

(<=3000)*(<=3000)的矩阵

上面有<=30000 个坏点

求 最大不含坏点的矩形面积

题解

因为求的是最大矩形,那么它的四周要么是边界,要么是坏点

证明:反证明

如果存在一条边既没有邻接 边界,也没有邻接坏点。

那么对该边延伸 ,可以得到更大的矩形,矛盾

观察到这个性质后

我们考虑对任意 点(i,j)

i0<i,其中(i0,j)为距离(i,j)最远的点 且 线段(i0->i,j)上无坏点

线(i0->i,j)为高,做横向扩张,找左右两侧的最近的坏点 或边界,则有以(i,j)搜寻的矩形面积=(i0->i,j) * 该线段左右扩张的最大宽度

  1. 这样找到的矩形 一定是 合法矩形 所以这样找到的矩形面积小于等于 最大面积
  2. 这样一定能找到最大的矩形,因为我们证明了最大矩形 一定邻接着坏点或边界,那么该最大矩形上方边界所对应的 坏点,正下方的的点 在运算过程会计算到

所以O(3000*3000),以所有点计算出一个矩形,每个矩形计算复杂度为O(1),即可

#include <bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--) using namespace std; const string filename = "rectbarn"; void usefile(){
freopen((filename+".in").c_str(),"r",stdin);
freopen((filename+".out").c_str(),"w",stdout);
} int L[3010],R[3010]; // j列当前线段 左右扩展的可行最远距离
int H[3010]; // j列 当前 的线段长度
bool g[3010][3010];
int n,m,ans;
int main(){
usefile();
freopen("rectbarn.in","r",stdin);
freopen("rectbarn.out","w",stdout);
int k;
cin>>n>>m>>k;
while(k--){
int i,j;
scanf("%d%d",&i,&j);
g[i][j]=1;
}
rep(j,0,m+1){
H[j]=0;
L[j]=1;
R[j]=m;
}
rep(i,1,n+1){
// 处理所有 坏点
rep(j,1,m+1){
if(g[i][j]){
H[j]=0;
L[j]=1;
R[j]=m;
}
}
// 计算所有 左侧 和 右侧 最远
int lm = 1;
rep(j,1,m+1){
if(!g[i][j]){
H[j]++;
L[j]=max(L[j],lm);
} else{
lm=j+1;
}
}
int rm = m;
per(j,1,m+1){
if(!g[i][j]){
R[j]=min(R[j],rm);
}else{
rm=j-1;
}
}
// 计算面积
rep(j,1,m+1){
if(!g[i][j]){
ans=max(ans,(R[j]-L[j]+1)*H[j]);
}
}
}
printf("%d\n",ans);
return 0;
}

Cow XOR

Adrian Vladu -- 2005

题目大意

n(<=100,000)个数,数值范围是[0,2^21 - 1]

求连续子区间 的最大xor值,输出 最大xor值,区间起始点,区间结束点

如果有多个区间满足最大异或,返回结束点index最小的,如果还有多个,返回长度最短的。

题解

首先

我们证明一下题目描述的结果唯一

如果多个 子区间 异或值相同,且结束点不同,那么 只有唯一可以选

如果两个 子区间 异或值相同,且结束点相同,那么 它们一定起始点不同,所以它们长度不同,只有最短可选

综上,题目描述结果唯一

然后

显然

xor[l->r] = xor[1->l-1]^xor[1->r]

所以 我们要找最大值,等于找两个前缀异或的最大值

从高位到低位,对所有前缀建立trie树,再for一遍贪心走trie树,贪心规则 有和当前位不同的走不同的路径,否则才走相同,(尽量在高位产生1)

空间 O(n*21),时间O(n*21)

空间节点数

s=0;
for i in range(0,22):
s+=min(2**i,100000)
print(s)

631071 个,然而 我开这么大会炸空间,开500000过的 (按道理讲 这样空间上看是开得有问题,开小了,不过过了测试)

我在实现过程中是找 区间左右端点靠的是 lower_bound二分,多用了空间,

然而,我们发现 最优区间必定有一个是 其前缀值的最小坐标

所以 如果枚举i去寻找 其期望的 前缀值对应的最小坐标,一定能找到最优值,可以优化

通过的,但空间开得不合理的代码,(我之前还用struct来写,虽然阅读上更好理解,但空间更加不够XD)

#include <bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--) using namespace std; const string filename = "cowxor"; void usefile(){
freopen((filename+".in").c_str(),"r",stdin);
freopen((filename+".out").c_str(),"w",stdout);
} int n;
int a[100010];
int p[100010];
int ns[500010][2]; int nsi=0; int *root = ns[nsi++]; map<int,vector<int> > pv2idx; // 前缀异或 到 下表 void build(int idx){
int v = p[idx];
pv2idx[v].push_back(idx); // ordered
int * po = root;
per(i,1,21){
int bit = !!(v&(1<<i));
if(!po[bit]){
po[bit] = nsi++;
}
po=ns[po[bit]];
}
int bit = !!(v&1);
po[bit] = v;
} int query(int idx){
int v = p[idx];
int * po = root;
per(i,1,21){
int bit = !(v&(1<<i));
if(!po[bit]){
po = ns[po[bit^1]];
}else{
po = ns[po[bit]];
}
}
int bit = !(v&1);
return po[bit] == 0?po[bit^1]:po[bit];
} int ans=-1,ansl,ansr; void setAns(int v1,int l,int r){
// cout<<"SETANS:"<<v1<<" l:"<<l<<" r:"<<r<<endl;
if(l > r){
swap(l,r);
}
if(v1 < ans)return;
if(v1 > ans){
ans = v1;
ansl = l;
ansr = r;
return ;
}
if(r < ansr){
ansl = l;
ansr = r;
return ;
}
if(r > ansr){
return ;
}
if(l > ansl){
ansl = l;
return ;
}
} int main(){
usefile();
scanf("%d",&n);
rep(i,0,n){
scanf("%d",a+i);
}
rep(i,0,n){
p[i+1]=p[i]^a[i];
}
rep(i,0,n+1){
build(i);
}
// for(auto item:pv2idx){
// cout<<"--------"<<item.first<<endl;
// for(auto z:item.second){
// cout<<z<<"\t"<<endl;
// }
// cout<<endl;
// }
rep(i,0,n+1){
int ret = query(i);
int reti = lower_bound(pv2idx[ret].begin(),pv2idx[ret].end(),i)-pv2idx[ret].begin();
// cout<<"find:"<<i<<"["<<p[i]<<"]:"<<ret<<"("<<pv2idx[ret][reti]<<")"<<endl;
if(ret == p[i]){
if(i > 0){
setAns(ret^p[i],i-1,i);
}
}else if(reti > 0){
setAns(ret^p[i],i,pv2idx[ret][reti-1]);
}else{
setAns(ret^p[i],i,pv2idx[ret][reti]);
}
}
printf("%d %d %d\n",ans,ansl+1,ansr);
return 0;
}

USACO 6.1 章节的更多相关文章

  1. USACO 6.4 章节

    The Primes 题目大意 5*5矩阵,给定左上角 要所有行,列,从左向右看对角线为质数,没有前导零,且这些质数数位和相等(题目给和) 按字典序输出所有方案... 题解 看上去就是个 无脑暴搜 题 ...

  2. USACO 6.3 章节 你对搜索和剪枝一无所知QAQ

    emmm........很久很久以前 把6.2过了 所以emmmmmm 直接跳过 ,从6.1到6.3吧 Fence Rails 题目大意 N<=50个数A1,A2... 1023个数,每个数数值 ...

  3. USACO 5.5 章节

    Picture 题目大意 IOI 1998 求n (<=5000)个矩形 覆盖的图形 的周长(包括洞), 坐标范围[-10000,10000] 题解 一眼离散化+2维线段树,但仔细一想 空间不太 ...

  4. USACO 5.4 章节

    Canada Tour 题目大意 双向连通图,点从左向右排列, 你需要先从最左的点到最右的点,(过程中只能从左向右走) 然后再从最右的点返回最左的点,(过程中只能从右向左走) 过程中除了最左的点,其它 ...

  5. USACO 5.3 章节

    相关讲解可在USACO上看原文,也可以搜索nocow找到翻译的! (nocow上有些微翻译是有问题的,如果想看nocow翻译的建议也对着英文看) 以下记录以下 自己之前未掌握的一些要点,以及按自己的括 ...

  6. USACO 6.5 章节 世界上本没有龙 屠龙的人多了也便有了

    All Latin Squares 题目大意 n x n矩阵(n=2->7) 第一行1 2 3 4 5 ..N 每行每列,1-N各出现一次,求总方案数 题解 n最大为7 显然打表 写了个先数值后 ...

  7. (Step1-500题)UVaOJ+算法竞赛入门经典+挑战编程+USACO

    http://www.cnblogs.com/sxiszero/p/3618737.html 下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年 ...

  8. 算法竞赛入门经典+挑战编程+USACO

    下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年到1年半年时间完成.打牢基础,厚积薄发. 一.UVaOJ http://uva.onlinej ...

  9. USACO . Your Ride Is Here

    Your Ride Is Here It is a well-known fact that behind every good comet is a UFO. These UFOs often co ...

随机推荐

  1. hive 排序

    1.全局排序(order by) Order by:全局排序,只有一个reducer ASC(ascend):升序(默认) DESC(descend):降序 2.每个MR内部排序(sort by) s ...

  2. [已解决]报错: Error response from daemon: conflict

    报错内容: Error response from daemon: conflict: unable to delete f5b6ef70d79b (must be forced) - image i ...

  3. 12、numpy——数学函数

    NumPy 数学函数 NumPy 包含大量的各种数学运算的函数,包括三角函数,算术运算的函数,复数处理函数等. 1.三角函数 NumPy 提供了标准的三角函数:sin().cos().tan(). i ...

  4. 55-python基础-python3-字典-删除键值对-del语句

    字典-键值对的彻底删除 对于字典中不再需要的信息,可使用del 语句将相应的键—值对彻底删除. 使用del 语句时,必须指定字典名和要删除的键. 注意  删除的键—值对永远消失了.

  5. 65.Longest Increasing Subsequence(最长增长子序列)

    Level:   Medium 题目描述: Given an unsorted array of integers, find the length of longest increasing sub ...

  6. Go语言_包、变量和函数

    包.变量和函数 学习 Go 程序的基本结构. Go 作者组编写,Go-zh 小组翻译. https://go-zh.org 包 每个 Go 程序都是由包构成的. 程序从 main 包开始运行. 本程序 ...

  7. [JavaScript深入系列]JavaScript深入之执行上下文栈(转载)

    顺序执行? 如果要问到 JavaScript 代码执行顺序的话,想必写过 JavaScript 的开发者都会有个直观的印象,那就是顺序执行,毕竟: var foo = function () { co ...

  8. elasticsearch 深入 —— 结构化搜索

    结构化搜索 结构化搜索(Structured search) 是指有关探询那些具有内在结构数据的过程.比如日期.时间和数字都是结构化的:它们有精确的格式,我们可以对这些格式进行逻辑操作.比较常见的操作 ...

  9. Dubbo源码学习总结系列一 总体认识

    本文写作时,dubbo最高版本是V2.6.0.  写这篇文章主要想回答以下4个问题: 一.dubbo是什么?完成了哪些主要需求? 二.dubbo适用于什么场景? 三.dubbo的总体架构是什么样的? ...

  10. 【串线篇】Mybatis之动态sql

    一.if标签 <select id="getTeacherByCondition" resultMap="teacherMap"> select * ...