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[]\)记录一下前缀和每个数出现了几 ...
随机推荐
- css美化checkbox radio样式
/*check,radio*/ input.check_txt[type='checkbox']{ display: none; } input.check_txt[type='checkbox'] ...
- 20160308001 GridView的Sorting排序
参考地址: http://www.cnblogs.com/yinluhui0229/archive/2011/08/01/2124169.html 功能介绍:单击gridview的某一列列头,可以对该 ...
- android 事件监听
步骤: 1.获取代表控件对象. 2.定义一个类,实现监听接口. 3.生成监听器对象. 4.为控件绑定监听器对象. XML <LinearLayout xmlns:android="ht ...
- php 中的常量
1.__FINE__ 返回当前常量所在的行号. 2.__FILE__ 返回文件的完整路径和文件名. 3.__FUNCTION__ 返回函数名称. 4.__CLASS__ 返回类名称. 5.__METH ...
- microstrip(微带线)、stripline(带状线) 指什么?
带状线:走在内层(stripline/double stripline),埋在PCB内部的带状走线,如下图所示 蓝色部分是导体,绿色部分是PCB的绝缘电介质,stripline是嵌在两层导体之间的带状 ...
- ★Java多线程编程总结 系列 转
下面是Java线程系列博文的一个编目: Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换 Java线程:线程的同步与锁 Jav ...
- C语言细节——献给初学者(二)
C语言细节——献给初学者(二) 主题 循环运用+选择判断 C语言循环有for和while/do...while: 选择判断有:if...else和switch...case 在循环中需要注意搭配br ...
- 程序设计入门——C语言 第1周编程练习 1逆序的三位数(5分)
第1周编程练习 查看帮助 返回 第1周编程练习题,直到课程结束之前随时可以来做.在自己的IDE或编辑器中完成作业后,将源代码的全部内容拷贝.粘贴到题目的代码区,就可以提交,然后可以查看在线编译和运 ...
- JQuery_高级选择器
在很多特殊的元素上,比如父子关系的元素,兄弟关系的元素,特殊属性的元素等等. 在早期 CSS 的使用上,由于 IE6 等低版本浏览器不支持,所以这些高级选择器的使用也不具备普遍性,但随着 jQuery ...
- 聊天界面之气泡文本cell(二)使用Autolayout
聊天界面主要是cell的动态高度计算和效率的问题,参考网上的两篇文章: 1.优化UITableViewCell高度计算的那些事 http://www.cocoachina.com/ios/20150 ...