CF#345 (Div1)
论蒟蒻如何被cf虐

以下是身败名裂后的题解菌===========
Div1 A.Watchmen
有n个点,每个点有一个坐标。求曼哈顿距离=欧几里得距离的点对数量。
只需要统计x或y一样的点对数量。容斥即可。注意long long。(sad story
//By zzq
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <set>
#include <map>
using namespace std;
int n;
typedef long long ll;
pair<int,int> sb[233333];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&sb[i].first,&sb[i].second);
sort(sb+1,sb+1+n);
ll x=0,y=0,xy=0;
for(int i=1;i<=n;i++)
{
int tot;
for(int j=i;j<=n;j++)
{
if(sb[j].first!=sb[i].first||sb[j].second!=sb[i].second) break;
tot=j;
}
xy+=(ll)(tot-i)*(tot-i+1)/2;
i=tot;
}
for(int i=1;i<=n;i++)
{
int tot;
for(int j=i;j<=n;j++)
{
if(sb[j].first!=sb[i].first) break;
tot=j;
}
x+=(ll)(tot-i)*(tot-i+1)/2;
i=tot;
}
for(int i=1;i<=n;i++) swap(sb[i].first,sb[i].second);
sort(sb+1,sb+1+n);
for(int i=1;i<=n;i++)
{
int tot;
for(int j=i;j<=n;j++)
{
if(sb[j].first!=sb[i].first) break;
tot=j;
}
y+=(ll)(tot-i)*(tot-i+1)/2;
i=tot;
}
cout<<x+y-xy<<"\n";
}
Div1 B.Image Preview
你的手机上有n张照片,相册是那种翻页的,也就是说你从i张照片向右翻,如果i=n,就会翻到第一张,否则翻到i+1张,向左翻类似。你翻一张照片要a的时间,然后有一些照片是横着的(w),有些是竖着的(h),如果照片是横着的,那么看前就要先旋转,旋转一张要b的时间。看一张照片要1的时间。开始你打开了第一张照片,你每打开一张没看过的照片就必须要看掉,总共有T的时间,问你最多能看几张照片。
题解:
比如n=7:1 2 3 4 5 6 7
可能会有如下几种方法是最优的:
(1) 1 2 3 4 5 类似这样从左往右直接看
(2) 1 2 3 2 1 7 6 5 先往右看几张,往回翻,再从n张开始往回看
(3) 1 7 6 5 6 7 1 2 3 看完第一张,先往左翻,往回看几张,再翻回第一张,再往右看几张
然后我们只要预处理出从第一张开始往后多少张要花多少时间,从最后一张往前多少张要花多少时间,然后分这三种情况二分或者尺取即可。因为懒所以用了二分…(最后交了五六次才过)
//By zzq
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
ll n,a,b,T,sl[2333333],sr[2333333];
char w[233333];
int main()
{
scanf("%I64d%I64d%I64d%I64d",&n,&a,&b,&T);
scanf("%s",w+1);
int ans=0;
{
ll ct=0;
for(int i=1;i<=n;i++)
{
char cp=w[i]; ll tm=1+a;
if(cp=='w') tm+=b;
ct+=tm; sl[i]=ct;
if(ct-a<=T) ans=max(ans,i);
}
}
{
ll ct=0;
for(int i=n;i>=1;i--)
{
char cp=w[i]; ll tm=1+a;
if(cp=='w') tm+=b;
ct+=tm; sr[i]=ct;
}
}
for(int i=1;i<=n;i++)
{
ll zbt=sl[i]+(i-2)*a;
if(zbt>T) continue;
int l=i+1,r=n+1;
while(l<r)
{
int mid=(l+r)>>1;
ll ct=zbt+sr[mid];
if(ct<=T) r=mid; else l=mid+1;
}
if(r==n+1) continue;
ans=max(ans,int(n-l+1+i));
}
for(int i=1;i<=n;i++)
{
ll zbt=sr[i]+(n-i)*a;
if(zbt>T) continue;
int l=0,r=i-1;
while(l<r)
{
int mid=(l+r+1)>>1;
ll ct=zbt+sl[mid];
if(ct<=T) l=mid; else r=mid-1;
}
if(r==0) continue;
ans=max(ans,int(n-i+1+l));
}
printf("%d\n",ans);
}
Div1 C.Table Compression
给你一个n*m的矩阵a,里面都是正整数,求一个正整数矩阵b使b中的最大数最小。对于每一行,a和b的相对顺序不变(即对于第i行,如果a[i][x]<a[i][y],那么b[i][x]<b[i][y],如果a[i][x]=a[i][y],那么b[i][x]=b[i][y],如果a[i][x]>a[i][y],那么b[i][x]>b[i][y]),每一列的相对顺序也不变。求一个最大数最小的b,多解输出任意一个。
每行每列排序,并查集缩一样的点,然后小于号连边,缩成DAG,跑一个类似拓扑排序的记忆化搜索即可。(我真的不知道怎么称呼这玩意儿
//By zzq
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <set>
#include <map>
using namespace std;
#define SZ 4333333
int n,m,gf[SZ],a[SZ];
#define ID(i,j) (((i)-1)*m+(j)-1)
typedef pair<int,int> pii;
pii ps[SZ];
int ff(int x) {return gf[x]?gf[x]=ff(gf[x]):x;}
void unionn(int a,int b)
{
int ga=ff(a),gb=ff(b);
if(ga!=gb) gf[ga]=gb;
}
int M=0,ma[SZ],mb[SZ];
int MM=0,fst[SZ],nxt[SZ],vb[SZ];
void adde(int a,int b)
{
++MM; nxt[MM]=fst[a]; fst[a]=MM; vb[MM]=b;
}
int dep[SZ]; bool vis[SZ];
int gd(int x)
{
if(vis[x]) return dep[x];
int mn=0;
for(int e=fst[x];e;e=nxt[e])
{
int b=vb[e];
mn=max(mn,gd(b));
}
vis[x]=1; return dep[x]=mn+1;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++) scanf("%d",&a[ID(i,j)]);
}
for(int i=1;i<=n;i++)
{
int pn=0;
for(int j=1;j<=m;j++) ps[++pn]=pii(a[ID(i,j)],j);
sort(ps+1,ps+1+pn);
for(int j=2;j<=pn;j++)
{
pii lst=ps[j-1],cur=ps[j];
int i1=ID(i,lst.second),i2=ID(i,cur.second);
if(lst.first==cur.first) unionn(i1,i2);
else ++M, ma[M]=i2, mb[M]=i1; //i1<i2
}
}
for(int j=1;j<=m;j++)
{
int pn=0;
for(int i=1;i<=n;i++) ps[++pn]=pii(a[ID(i,j)],i);
sort(ps+1,ps+1+pn);
for(int i=2;i<=pn;i++)
{
pii lst=ps[i-1],cur=ps[i];
int i1=ID(lst.second,j),i2=ID(cur.second,j);
if(lst.first==cur.first) unionn(i1,i2);
else ++M, ma[M]=i2, mb[M]=i1; //i1<i2
}
}
for(int i=1;i<=M;i++)
{
int a=ma[i],b=mb[i];
int f1=ff(a),f2=ff(b);
adde(f1,f2);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++) gd(ff(ID(i,j)));
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++) printf("%d ",dep[ff(ID(i,j))]);
printf("\n");
}
}
Div1 D.Zip-line
给一个长度为n的序列h和m次询问。每次询问要求把一个位置上的数改成某一个值,询问LIS。询问互相独立。
考虑新的LIS中存不存在被修改的元素。
如果存在。因为询问可以离线,我们把询问排个序,在求LIS的时候顺便求一下带上这个修改后的元素的LIS。
如果不存在。如果LIS必须经过这个元素,那么长度就会-1,否则不变。
我们用L[i]表示以i结尾的LIS长度,R[i]表示以i开头的LIS长度。
那么设整个序列LIS为p,如果L[x]+R[x]-1=p那么x至少在一个LIS中对吧。那么如果x至少存在于一个LIS中且不存在其他的j使得L[j]=L[x],那么LIS的第L[x]位就必须为x。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <limits>
#include <set>
#include <map>
using namespace std;
int inf=1000000000;
#define SZ 666666
int n,a[SZ],len,lt[SZ],L[SZ],R[SZ],q,ql[SZ],qr[SZ],col[SZ];
struct Tuple {int a,b,id;} qs[SZ];
bool c1(Tuple a,Tuple b) {return a.a<b.a;}
bool c2(Tuple a,Tuple b) {return a.a>b.a;}
bool c3(Tuple a,Tuple b) {return a.id<b.id;}
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) scanf("%d",a+i);
for(int i=1;i<=q;i++) scanf("%d %d",&qs[i].a,&qs[i].b), qs[i].id=i;
int cur;
sort(qs+1,qs+1+q,c1);
cur=1; len=0;
memset(lt,0,sizeof(lt));
for(int i=1;i<=n;i++)
{
int cl;
while(cur<=q&&qs[cur].a==i)
{
int ans,c=qs[cur].b;
if(!len||c>lt[len]) ans=len+1;
else ans=lower_bound(lt+1,lt+1+len,c)-lt;
ql[qs[cur].id]=ans;
++cur;
}
if(i!=1)
{
if(a[i]>lt[len]) lt[cl=++len]=a[i];
else lt[cl=lower_bound(lt+1,lt+1+len,a[i])-lt]=a[i];
}
else lt[1]=a[1], cl=1, len=1;
L[i]=cl;
}
int lis=len;
sort(qs+1,qs+1+q,c2);
for(int i=1;i<=n;i++) a[i]=inf-a[i];
cur=1; len=0;
memset(lt,0,sizeof(lt));
for(int i=n;i>=1;i--)
{
int cl;
while(cur<=q&&qs[cur].a==i)
{
int ans,c=inf-qs[cur].b;
if(!len||c>lt[len]) ans=len+1;
else ans=lower_bound(lt+1,lt+1+len,c)-lt;
qr[qs[cur].id]=ans;
++cur;
}
if(i!=n)
{
if(a[i]>lt[len]) lt[cl=++len]=a[i];
else lt[cl=lower_bound(lt+1,lt+1+len,a[i])-lt]=a[i];
}
else lt[1]=a[n], cl=1, len=1;
R[i]=cl;
}
for(int i=1;i<=n;i++)
{
if(L[i]+R[i]-1!=lis) continue;
col[L[i]]++;
}
sort(qs+1,qs+1+q,c3);
for(int p=1;p<=q;p++)
{
int i=qs[p].a;
int a1=ql[p]+qr[p]-1;
bool met=L[i]+R[i]-1==lis&&col[L[i]]==1;
int a2=lis-met;
printf("%d\n",max(a1,a2));
}
}
E题施工中…
CF#345 (Div1)的更多相关文章
- CF #345 Div1 D Zip-line
题目链接:http://codeforces.com/contest/650/problem/D 大意是给一个数组,若干询问,每一次把一个数字改为另一个数字,问当前数组最长上升子序列,询问之间是独立的 ...
- CF#462 div1 D:A Creative Cutout
CF#462 div1 D:A Creative Cutout 题目大意: 原网址戳我! 题目大意: 在网格上任选一个点作为圆中心,然后以其为圆心画\(m\)个圆. 其中第\(k\)个圆的半径为\(\ ...
- CF #356 div1 A. Bear and Prime 100
题目链接:http://codeforces.com/contest/679/problem/A CF有史以来第一次出现交互式的题目,大致意思为选择2到100中某一个数字作为隐藏数,你可以询问最多20 ...
- 【Codeforces】#345 Div1
1. Watchmen1.1 题目描述给$n$个点,求曼哈顿距离等于欧式距离的点对数. 1.2 基本思路由$|x_i-x_j|+|y_i-yj| = \sqrt{(x_i-x_j)^2+(y_i-yj ...
- CF#345 div2 A\B\C题
A题: 贪心水题,注意1,1这组数据,坑了不少人 #include <iostream> #include <cstring> using namespace std; int ...
- CF #228 div1 B. Fox and Minimal path
题目链接:http://codeforces.com/problemset/problem/388/B 大意是用不超过1000个点构造一张边权为1的无向图,使得点1到点2的最短路的个数为给定值k,其中 ...
- CF #349 div1 B. World Tour
题目链接:http://codeforces.com/problemset/problem/666/B 大意是给一张有向图,选取四个点,使得走这四个点,任意两个点之间走最短路,总距离最长. 3000个 ...
- CF #335 div1 A. Sorting Railway Cars
题目链接:http://codeforces.com/contest/605/problem/A 大意是对一个排列进行排序,每一次操作可以将一个数字从原来位置抽出放到开头或结尾,问最少需要操作多少次可 ...
- CF #299 div1 B. Tavas and Malekas KMP-next数组
题目链接:http://codeforces.com/contest/536/problem/B 一个原始字符串,一个未知字符串,每一次从pos[i]开始覆盖未知字符串,问最后字符串的形式,以及判断过 ...
随机推荐
- 修改 Android 5.x 系统默认音量大小
修改系统默认音量需要改两处地方: 1. frameworks\base\media\java\android\media\AudioManager.java /** @hide Default vol ...
- 【代码笔记】iOS-点击搜索跳转到另外一个页面
一,效果图. 二,工程图. 三,代码. RootViewController.h #import <UIKit/UIKit.h> @interface RootViewController ...
- 【读书笔记】iOS-ARC-Xcode检测循环引用
一,在桌面上新建立一个工程,在ViewController.m中输入如下代码: - (void)viewDidLoad { [super viewDidLoad]; // Do any additio ...
- js中转换Date日期格式
在javascript中直接输出Date得到的结果是这样的: function date(){ var date = new Date(); alert(date); } 结果是:Mon Jun 15 ...
- (视频) 《快速创建网站》3.4 网站改版3分钟搞定 - WordPress主题安装和备份
本文是<快速创建网站>系列的第8篇,如果你还没有看过之前的内容,建议你点击以下目录中的章节先阅读其他内容再回到本文. 访问本系列目录,请点击:http://devopshub.cn/tag ...
- Ember.js 应用入口
大凡研究一套系统,调试一段代码,最先需要做的就是找到入口, 话说师傅领进门,修行在个人.找到入口,找到门,路就可以自己一步一步的往下走. Ember强大不? 强大! 好不? 看看流行度就知道了, 远比 ...
- Linux 执行partprobe命令时遇到Unable to open /dev/sr0 read-write (Read-only file system)
在使用fdisk创建分区时,我们会使用partprobe命令可以使kernel重新读取分区信息,从而避免重启系统,但是有时候会遇到下面错误信息"Warning: Unable to open ...
- 自定义底部工具栏及顶部工具栏和Fragment配合使用demo
首先简单的介绍下fragment,fragment是android3.0新增的概念,其中文意思是碎片,它与activity非常相似,用来在一个activity中描述一些行为或一部分用户界面.使用锁个f ...
- html5+css3实现跑动的爱心/动态水滴效果[原创][5+3时代]
大风起兮云飞扬,安得猛士兮走四方!html5+css3,不学不行. 做web开发已经有好几年了,见证了太多语言的崛起和陨落. 其实作为一个程序员最苦逼的事情莫过于每天要不停的追赶各大公司新出的框架和语 ...
- WebService 实例
使用Java WebService API实现 1.服务端接口: package com.h3c.itac.webservice; import javax.jws.WebService; @WebS ...