ACM 杂题,思路题 整理
UVa 11572 - Unique Snowflakes
问一个数组中,无重复数字的最长子串长度是多少。
用map维护某数字上次出现的位置。另外用变量last表示上次出现数字重复的位置。
如果出现重复数字,且map[val]>last时,计算当前区间长度,然后last变为map[val]+1。
其他时候增长区间长度即可。
每次遍历一个元素都要更新map[val],用区间长度更新最优解。
#include<iostream>
#include<vector>
#include<cmath>
#include<map>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<string>
#define INF 1000000000LL
#define ll long long
using namespace std;
map<int,int> mp;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
mp.clear();
int n;
scanf("%d",&n);
,res=,last=;
; i<=n; ++i)
{
int v;
scanf("%d",&v);
int &u=mp[v];
if(!u||u<last) res++;
else
{
res=i-u;
last=u+;
}
u=i;
ans=max(ans,res);
}
printf("%d\n",ans);
}
;
}
UVa 1152 - 4 Values whose Sum is 0
中途相遇法。重点在于写哈希的部分。
#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<string>
#define ll long long
using namespace std;
struct Hash_map
{
static const int mask=0x7fffff;
],q[];
void clear()
{
; i<=mask; ++i)
q[i]=;
}
int& operator [](int k)
{
int i;
)&mask);
p[i]=k;
return q[i];
}
};
][];
Hash_map hash;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
hash.clear();
; i<n; ++i)
scanf(][i],&arr[][i],&arr[][i],&arr[][i]);
; i<n; ++i)
; j<n; ++j)
hash[arr[][i]+arr[][j]]++;
;
; i<n; ++i)
; j<n; ++j)
ans+=hash[-(arr[][i]+arr[][j])];
printf("%d\n",ans);
if(T)putchar('\n');
}
;
}
ZOJ 3278 8G Island
给两个数组,A和B,求第k大个Ai*Bj的数字。这里要注意是求第k大,不是第k小。相当于求第n*m-k小数字。
二分答案,统计比该答案小的结果有多少个。这样问题就变成了求一个满足比它小的数超过(n*m-k)的最小数。
需要快速求比该数小的元素个数,这样枚举Ai,再计算b=val/Ai,快速统计比不超过b的Bj有多少个,这样可以求得。可以用二分也可以用前缀和的性质。
注意要用longlong。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<iostream>
#define LL long long
using namespace std;
LL n,m,K;
const LL maxn= 1e10;
;
vector<int> a,b;
],bsum[];
LL judge(LL val)
{
LL cnt=;
if(a.size()<b.size())
{
; i<a.size(); ++i)
{
LL p=min(val/a[i],maxm);
cnt+=bsum[p];
}
}
else
{
; i<b.size(); ++i)
{
LL p=min(val/b[i],maxm);
cnt+=asum[p];
}
}
return cnt;
}
LL BinSearch(LL low,LL high)
{
LL mid=(low+high)/;
while(low<high)
{
if(judge(mid)>=K) high=mid;
;
mid=(low+high)/;
}
return mid;
}
int main()
{
while(cin>>n>>m>>K)
{
int u;
a.clear();
b.clear();
; i<n; ++i)
{
cin>>u;
a.push_back(u);
}
; i<m; ++i)
{
cin>>u;
b.push_back(u);
}
memset(asum,,sizeof(asum));
memset(bsum,,sizeof(bsum));
; i<a.size(); ++i)
asum[a[i]]++;
; i<=maxm; ++i)
asum[i]+=asum[i-];
; i<b.size(); ++i)
bsum[b[i]]++;
; i<=maxm; ++i)
bsum[i]+=bsum[i-];
K=n*m-K+;
cout<<BinSearch(,maxn)<<endl;
}
;
}
UVa 11491 Erasing and Winning
给一个长度为n的数字,问删掉d个数字后可能取得的最大数字是多少?
思路比较好想,考虑留下的n-d个数字,每次在保证最终可以选到n-d-i个数字的前提下,选最大的数字,这个选数的过程可以用线段树完成,同时维护区间最大值和最大值下标,注意优先选最左边的。复杂度n*logn。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<iostream>
#define inf -100000000
#define LL long long
#define MAXN 100001<<2
using namespace std;
struct SegmentTree
{
int maxv[MAXN],pos[MAXN];
void push_up(int o)
{
]>=maxv[o<<|])
{
maxv[o]=maxv[o<<];
pos[o]=pos[o<<];
}
else
{
maxv[o]=maxv[o<<|];
pos[o]=pos[o<<|];
}
}
void build(int o,int L,int R)
{
if(L==R)
{
char c=getchar();
maxv[o]=c-';
pos[o]=L;
}
else
{
;
build(o<<,L,M);
build(o<<|,M+,R);
push_up(o);
}
}
int query(int o,int L,int R,int ql,int qr,int &p,int &maxn)
{
if(ql<=L&&R<=qr)
{
if(maxv[o]>maxn)
{
maxn=maxv[o];
p=pos[o];
}
return maxn;
}
else
{
;
,b=;
,L,M,ql,qr,p,maxn);
|,M+,R,ql,qr,p,maxn);
return max(a,b);
}
}
};
SegmentTree tree;
int N,D;
int main()
{
while(scanf("%d%d",&N,&D)!=EOF)
{
if(!N&&!D) break;
getchar();
tree.build(,,N);
getchar();
,pos;
; i<=N-D; ++i)
{
;
,,N,p,d,pos,maxn);
printf("%d",r);
p=pos+;
}
printf("\n");
}
;
}
UVa 787 Maximum Sub-sequence Product
问最大子数组乘积是多少。数据量不大,n^2可做。要用大数,所以写了java。
import java.math.BigInteger;
import java.util.Scanner;
public class Main
{
public static void main(String[] args) {
BigInteger[] a = new BigInteger[101];
for (int i = 0; i <= 100; ++i)
a[i] = new BigInteger("0");
BigInteger maxnBigInteger = new BigInteger("-999999");
Scanner inScanner = new Scanner(System.in);
while (inScanner.hasNextBigInteger()) {
int n = 0;
while (true) {
a[n] = inScanner.nextBigInteger();
if (a[n].compareTo(maxnBigInteger) == 0)
break;
n++;
}
BigInteger ansBigInteger = new BigInteger("1");
ansBigInteger = ansBigInteger.multiply(a[0]);
for (int i = 0; i < n; ++i) {
BigInteger resBigInteger = new BigInteger("1");
for (int j = i; j < n; ++j) {
resBigInteger = resBigInteger.multiply(a[j]);
ansBigInteger = ansBigInteger.max(resBigInteger);
}
}
System.out.println(ansBigInteger);
}
}
}
UVa 11536 Smallest Sub-Array
求一个出现全部1-K的数字的最小数组长度。
分别用一个首、尾指针维护一个区间,使区间内出现要求的全部k个数字。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <algorithm>
#define ll long long
#define INF 2139062143
#define inf -2139062144
#define MOD 20071027
using namespace std;
int N,M,K;
];
],cnt;
bool judge(int a)
{
<=a&&a<=K;
}
int main()
{
;
//freopen("out.txt","w",stdout);
scanf("%d",&T);
a[]=;
a[]=;
a[]=;
while(T--)
{
scanf("%d%d%d",&N,&M,&K);
; i<=N; ++i)
a[i]=(a[i-]+a[i-]+a[i-])%M+;
memset(vis,,sizeof(vis));
cnt=;
;
;
; i<=N; ++i)
{
if(judge(a[i]))
{
) cnt++;
vis[a[i]]++;
}
while(j<=i&&cnt==K)
{
if(!judge(a[j])) j++;
!=)
{
vis[a[j]]--;
j++;
}
else break;
}
if(cnt==K)
{
) ans=i-j+;
);
}
}
printf("Case %d: ",++kase);
) puts("sequence nai");
else printf("%d\n",ans);
}
;
}
与最大子序列和相关的一些题型。
最经典的是1维的最大连续数组和,O(n)DP可做。2维就要用前缀和+DP。
此类题可变形为求值小于K的最大连续数组和,1维则用尺取法维护区间,同步维护区间和和最短区间长度。2维同样利用这个思想,再加前缀和。
UVa 11951 Area
求小于给定数值的最大面积子矩阵,而且权值尽量小。
属于上面的变形题的2维。用滑动窗口维护即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <algorithm>
#define LL long long
#define INF 2139062143
#define inf -2139062144
#define MOD 20071027
using namespace std;
][];
][];
LL K;
void maintain(int ta,LL ts,int &area,LL &cost)
{
if(ta>area) cost=ts;
else if(ta==area) cost=min(cost,ts);
area=max(area,ta);
}
int main()
{
;
//freopen("out.txt","w",stdout);
scanf("%d",&T);
while(T--)
{
int N,M;
scanf("%d%d%lld",&N,&M,&K);
; i<=N; ++i)
; j<=M; ++j)
scanf("%d",&mat[i][j]);
LL cost=;
;
; i<=N; ++i)
; j<=M; ++j)
sum[i][j]=sum[i][j-]+mat[i][j];
; i<=M; ++i)
for(int j=i; j<=M; ++j)
{
;
LL s=;
,ed=;
while(ed<=N)
{
];
if(a>K)
{
ed=st=ed+;
s=;
continue;
}
while(st<ed&&s+a>K)
{
];
s-=b;
st++;
}
while(ed<=N&&s+a<=K)
{
s+=a;
ed++;
];
}
if(s<=K)
maintain((ed-st)*L,s,area,cost);
}
}
printf("Case #%d: %d %lld\n",++kase,area,cost);
}
;
}
UVa 10667 Largest Block
求最大空白矩形。前缀和求连续和,预处理一个数组判断某个区间是否为空。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
][];
][];
bool isEmpty(int c,int L,int R)
{
==sum[c][R]-sum[c][L-];
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int s,b;
scanf("%d%d",&s,&b);
int r1,c1,r2,c2;
memset(grid,,sizeof(grid));
;i<b;++i)
{
scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
for(int j=r1;j<=r2;++j)
for(int k=c1;k<=c2;++k)
grid[j][k]=false;
}
memset(sum,,sizeof(sum));
;i<=s;++i)
;j<=s;++j)
sum[i][j]=sum[i][j-]+(int)grid[i][j];
;
;i<=s;++i)
for(int j=i;j<=s;++j)
{
;
;
;k<=s;++k)
{
;
else {
res+=L;
ans=max(ans,res);
}
}
}
printf("%d\n",ans );
}
;
}
ACM 杂题,思路题 整理的更多相关文章
- Rectangles(第七届ACM省赛原题+最长上升子序列)
题目链接: http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=1255 描述 Given N (4 <= N <= 100) rec ...
- 第13届 广东工业大学ACM程序设计大赛 C题 平分游戏
第13届 广东工业大学ACM程序设计大赛 C题 平分游戏 题目描述 转眼间又过了一年,又有一届的师兄师姐要毕业了. 有些师兄师姐就去了景驰科技实习. 在景驰,员工是他们最宝贵的财富.只有把每一个人 ...
- 蓝桥杯java历年真题及答案整理1~20.md
蓝桥杯java历年真题及答案整理(闭关一个月,呕心沥血整理出来的) 1 算法是这样的,如果给定N个不同字符,将这N个字符全排列,最终的结果将会是N!种.如:给定 A.B.C三个不同的字符,则结果为:A ...
- 51nod P1305 Pairwise Sum and Divide ——思路题
久しぶり! 发现的一道有意思的题,想了半天都没有找到规律,结果竟然是思路题..(在大佬题解的帮助下) 原题戳>>https://www.51nod.com/onlineJudge/ques ...
- acm.njupt 1001-1026 简单题
点击可展开上面目录 Acm.njupt 1001-1026简单题 第一页许多是简单题,每题拿出来说说,没有必要,也说不了什么. 直接贴上AC的代码.初学者一题题做,看看别人的AC代码,寻找自己的问题. ...
- POJ 1904 思路题
思路: 思路题 题目诡异地给了一组可行匹配 肯定有用啊-. 就把那组可行的解 女向男连一条有向边 如果男喜欢女 男向女连一条有向边 跑一边Tarjan就行了 (这个时候 环里的都能选 "增广 ...
- sql 经典查询50题 思路(一)
因为需要提高一下sql的查询能力,当然最快的方式就是做一些实际的题目了.选择了这个sql的50题,这次大概做了前10题左右,把思路放上来,也是一个总结. 具体题目见: https://zhuanlan ...
- BZOJ 3252: 攻略(思路题)
传送门 解题思路 比较好想的一道思路题,结果有个地方没开\(long\) \(long\) \(wa\)了三次..其实就是模仿一下树链剖分,重新定义重儿子,一个点的重儿子为所有儿子中到叶节点权值最大的 ...
- BZOJ 1303: [CQOI2009]中位数图(思路题)
传送门 解题思路 比较好想的思路题.首先肯定要把原序列转化一下,大于\(k\)的变成\(1\),小于\(k\)的变成\(-1\),然后求一个前缀和,还要用\(cnt[]\)记录一下前缀和每个数出现了几 ...
随机推荐
- web页面状态
200 :表示请求成功,服务器已处理 201 :表示服务器端请求被创建, 202 :表示服务器端请求已经被接收,但未处理完成 400 :表示错误的请求 404:表示请求的资源未找到. 405:表示没有 ...
- android 蓝牙串口通讯使用简介
需要的权限 <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-perm ...
- (8) 深入理解Java Class文件格式(七)
转载:http://blog.csdn.net/zhangjg_blog/article/details/22091529 本专栏列前面的一系列博客, 对Class文件中的一部分数据项进行了介绍. 本 ...
- stoneniqiu 理想就是自己喜欢做,并对社会和他人都有意义的事情!
H5嵌入原生开发小结----兼容安卓与ios的填坑之路 2016-11-19 08:29 by stoneniqiu, 1038 阅读, 8 评论, 收藏, 编辑 一开始听说开发H5,以为就是做适配现 ...
- CentOs 设置静态IP 方法
在做项目时由于局域网采用自动获取IP的方式,导到每次服务器重启主机IP都会变化. 为了解决这个问题,需要设置静态IP. 1.修改网卡配置 编辑:vi /etc/sysconfig/network-sc ...
- php实战正则表达式:验证手机号
摘自http://www.tuicool.com/articles/MFNZRzu 本文通过逐步完善一个验证手机号的正则表达式来介绍了正则表达式中的 字符组 .量词 . 字符串起始/结束位置 . 分组 ...
- 13.KVM安装之网桥
安装必须的几个库和软件(最好下载一个163的yum源,速度快点) $ yum -y install kvm python-virtinst libvirt tunctl bridge-utils vi ...
- Linux信号基础
Linux信号基础 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Linux进程基础一文中已经提到,Linux以进程为单位来 ...
- BZOJ 2286: [Sdoi2011]消耗战
2286: [Sdoi2011消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2082 Solved: 736[Submit][Status] ...
- [转]MySQL去除重复数据
亲测可行,看这里就行了 http://www.jb51.net/article/39302.htm