【hackerrank】Week of Code 30
Candy Replenishing Robot
Find the Minimum Number
直接模拟
Melodious password
dfs输出方案
Poles
题意:有多个仓库,只能从后面的仓库运动前面的仓库,现在要把仓库合并成k个,移动一个仓库i到另个仓库j的代价是costi*(xi-xj),问最小代价。
解一下就会发现是个斜率优化,做k次就可以了
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 100101
#define LL long long
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define dow(i,l,r) for(int i=r;i>=l;i--)
using namespace std; LL sumd[maxn],sumw[maxn],f[][maxn],d[maxn],w[maxn];
int n,m,p[maxn]; LL calc(int x,int y)
{
return f[y][x]-sumd[x];
}
int main()
{
scanf("%d %d",&n,&m);
dow(i,,n) scanf("%lld %lld",&d[i],&w[i]);
rep(i,,n) {
sumw[i]=sumw[i-]+w[i];
sumd[i]=sumd[i-]+d[i]*w[i];
}
// rep(i,1,n) printf("%d %lld %lld %lld\n",i,d[i],sumw[i],sumd[i]);printf("\n");
int now=;
rep(i,,n) f[][i]=-(sumw[i]-sumw[])*d[i]+sumd[i]-sumd[];
// rep(i,1,n) printf("%lld ",f[0][i]);printf("\n");
rep(i,,m) {
now=-now;
rep(j,,n) f[now][j]=;
int head,tail;
head=tail=;
p[]=i-;
rep(j,i,n) {
// printf("%d %d\n",head,tail);
// rep(k,head,tail) printf("%d ",p[k]);printf("\n");
while (head<tail &&
d[j]*(sumw[p[head+]]-sumw[p[head]])<calc(p[head],-now)-calc(p[head+],-now))
++head;
f[now][j]=(sumw[p[head]]-sumw[j])*d[j]+(sumd[j]-sumd[p[head]])+f[-now][p[head]];
// printf("%lld %lld\n",calc(p[tail],1-now),calc(j,1-now));
while (head<tail &&
(calc(p[tail],-now)-calc(j,-now))*(sumw[p[tail]]-sumw[p[tail-]])>(calc(p[tail-],-now)-calc(p[tail],-now))*(sumw[j]-sumw[p[tail]]))
--tail;
p[++tail]=j;
}
// rep(j,1,n) printf("%lld ",f[now][j]);printf("\n");
}
printf("%lld\n",f[now][n]);
return ;
}
Range Modular Queries
给一个数组,每次查询[l,r]中取模x为y的个数。
我使用莫队直接写的,复杂度比较迷,其实可以预处理出模数为[1,10]的情况再莫队
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define maxn 50000
#define LL long long
#define rep(i,l,r) for(int i=l;i<=r;i++)
using namespace std; typedef struct {
int l,r,k,id,x,y;
}Que;
Que que[maxn];
int cmp(Que x,Que y)
{
if (x.k!=y.k) return x.k<y.k;
return x.r<y.r;
}
int num[maxn],c[maxn],n,m,ans[maxn]; int main()
{
scanf("%d %d",&n,&m);
rep(i,,n-) scanf("%d",num+i);
int len=sqrt(n);
rep(i,,m-) {
scanf("%d %d %d %d",&que[i].l,&que[i].r,&que[i].x,&que[i].y);
que[i].id=i;
que[i].k=que[i].l/len;
}
sort(que,que+m,cmp);
int i=;
while (i<m) {
// printf("%d\n",i);
int k=que[i].k;
memset(c,,sizeof(c));
rep(j,que[i].l,que[i].r) ++c[num[j]];
int now;
now=que[i].y;
while (now<maxn) ans[que[i].id]+=c[now],now+=que[i].x;
// printf("!!\n");
++i;
while (que[i].k==k&&i<m) {
// printf("!!\n");
rep(j,que[i].l,que[i-].l-) c[num[j]]++;
rep(j,que[i-].l,que[i].l-) c[num[j]]--;
rep(j,que[i-].r+,que[i].r) c[num[j]]++;
rep(j,que[i].r+,que[i-].r) c[num[j]]--;
now=que[i].y;
while (now<maxn) ans[que[i].id]+=c[now],now+=que[i].x;
++i;
}
// printf("!!!\n");
}
rep(i,,m-) printf("%d\n",ans[i]);
return ;
}
标解的方法显然更好,
分两部分处理,1-k和k到n(k=sqrt(n));
对于第一部分,建立一个pos[i][j]的vector表示模数为i,结果为j的数的下标,每次查询就直接二分找出下标,相减就是个数。
对于第二部分,建立一个poss[i]的vector表示数为i的下标,对于每次询问从x开始,每次查询l,r区间有多少个这个数,一样是二分查找下标相减
A Graph Problem
题意:给一个图,让你选出其中一些点,使得这些点中边组成的三角形/点的个数最大。
求比值最大显然是01分数规划,化简一下就是y-g*x=0,这是一个最大权闭合图,用网络流建图解决。记住收益=正的收益-最小割(最大流),收益>0就是存在方案。不过最后要输出方案我gg了,一个是精度,另一个是最后要用l重新跑一遍,然后找出和s不在一个集合的点,就是从s开始dfs找不到的点,
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define LL long long
#define maxn 100000
#define maxm 100000
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define dow(i,l,r) for(int i=r;i>=l;i--)
#define repedge(i,x) for(int i=cur[x];i>=0;i=e[i].next)
#define repedge2(i,x) for(int i=cur[x];i>=0;i=e[i].next)
#define inf 10000
using namespace std; typedef struct {
int toward,next;
double cap;
} Edge; Edge e[maxm];
int d[maxn],chose[maxn],gap[maxn],fi[maxn],cur[maxn],n,m,tot1,total,tar[maxn][],ap[][],s,t;
double esp=0.000000001; void add(int j,int k,double l)
{
e[total].toward=k;
e[total].next=fi[j];
fi[j]=total;
e[total].cap=l;
++total;
} void addedge(int j,int k,double l)
{
add(j,k,l);
add(k,j,);
} double sap(int x,double flow)
{
// printf("%d %lf\n",x,flow);
if (x==t) return flow;
double now=;
repedge(i,x) {
int too=e[i].toward;
if (d[x]==d[too]+ && e[i].cap>) {
double more=sap(too,min(e[i].cap,flow-now));
e[i].cap-=more;
e[i^].cap+=more;
cur[x]=i;
if (flow==(now+=more)) return flow;
}
}
if (!(--gap[d[x]])) d[s]=t;
gap[++d[x]]++;
cur[x]=fi[x];
return now;
} double maxflow()
{
rep(i,,t) d[i]=,gap[i]=,cur[i]=fi[i];
gap[]=t;
double sum=;
while (d[s]<t) sum+=sap(s,inf);
return sum;
} void dfs(int x)
{
// printf("%d\n",x);
chose[x]=;
repedge2(i,x) {
int too=e[i].toward;
// printf("\t%d %lf\n",too,e[i].cap);
if (e[i].cap>esp && !chose[too]) dfs(too);
}
}
int main()
{
scanf("%d",&n);
rep(i,,n)
rep(j,,n) scanf("%d",&ap[i][j]);
tot1=;
rep(i,,n)
rep(j,i+,n)
rep(k,j+,n)
if (ap[i][j] && ap[i][k] && ap[j][k]) {
++tot1;
tar[tot1][]=i;
tar[tot1][]=j;
tar[tot1][]=k;
}
s=n+tot1+;t=n+tot1+;
double l=,r=;
while (r-l>=esp) {
double mid=(l+r)/2.0;
// printf("%lf\n",mid);
total=;
rep(i,,t) fi[i]=-;
rep(i,,tot1)
rep(j,,) addedge(tar[i][j],i+n,inf);
rep(i,,n) addedge(s,i,mid);
rep(i,,tot1) addedge(i+n,t,);
if (tot1-maxflow()>) l=mid;
else r=mid;
}
// printf("%lf %lf %lf\n",l,r,(l+r)/2);
total=;
rep(i,,t) fi[i]=-;
rep(i,,tot1)
rep(j,,) addedge(tar[i][j],i+n,inf);
rep(i,,n) addedge(s,i,l);
rep(i,,tot1) addedge(i+n,t,);
maxflow();
memset(chose,,sizeof(chose));
dfs(s);
int tot2=;
rep(i,,n) if (!chose[i]) ++tot2;
printf("%d\n",tot2);
rep(i,,n) if (!chose[i]) printf("%d ",i);
printf("\n");
return ;
}
Substring Queries
给多个字符串,求出其中某两个字符串的lcp。
建立一个广义后缀数组。然后记录每个字符串的后缀在sa[]中的位置,对于一个询问,s1,s2,取出s1的每一个后缀和s2的每一个后缀算一个lcp,可以发现只会和s2中最接近这个后缀的两个后缀有关系,也就是每次都是单调的,一次询问就是s1+s2的后悔次数,然后做两个小优化,一个是把询问一样的一起处理,一个是每次s1选取那个短一点的,最后摊下来是一个比较好看的复杂度。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define maxn 210000
#define maxm 210000
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define dow(i,l,r) for(int i=r;i>=l;i--)
using namespace std; vector<int> vec[maxn];
int len,n,f[][maxn],tot,sa[maxn],ran[maxn],h[maxn],num[maxn],d[maxn],ans[maxn],x[maxn],y[maxn],c[maxn],m,size[maxn],col[maxn];
char s[maxn],st[maxn]; typedef struct {
int l,r,id;
}Que;
Que que[maxn];
int cmp(Que a,Que b)
{
if (a.r!=b.r) return a.r<b.r;
return a.l<b.l;
} void makesa()
{
for(int p=;p<len;p*=) {
// printf("%d\n",p);
rep(i,,p) y[i]=len-p+i;
int j=p;
rep(i,,len)
if (sa[i]>p) y[++j]=sa[i]-p;
rep(i,,len) x[i]=ran[y[i]];
memset(c,,sizeof(c));
rep(i,,len) c[x[i]]++;
rep(i,,tot) c[i]+=c[i-];
dow(i,,len) sa[c[x[i]]--]=y[i];
x[sa[tot=]]=;
rep(i,,len) {
tot+=(ran[sa[i]]!=ran[sa[i-]] || ran[sa[i]+p]!=ran[sa[i-]+p]);
x[sa[i]]=tot;
}
rep(i,,len) ran[i]=x[i];
// rep(i,1,len) printf("%s\n",&s[sa[i]]);
if (tot==len) break;
}
rep(i,,len) sa[ran[i]]=i;
} void makeheight()
{
h[]=;
int last=;
rep(i,,len) {
last=max(last-,);
if (ran[i]==) continue;
int j=sa[ran[i]-];
while (s[i+last]==s[j+last]) ++last;
h[ran[i]]=last;
}
} void into()
{
scanf("%d %d",&n,&m);
len=;
rep(i,,n) {
scanf("%s",st);
size[i]=strlen(st);
s[++len]='#';
rep(j,,size[i]-) {
s[++len]=st[j];
d[len]=size[i]-j;
col[len]=i;
}
}
s[++len]='$';
memset(c,,sizeof(c));
rep(i,,len) c[x[i]=s[i]]++;
rep(i,,) c[i]+=c[i-];
dow(i,,len) sa[c[x[i]]--]=i;
ran[sa[tot=]]=;
rep(i,,len)
ran[sa[i]]=(tot+=(x[sa[i]]!=x[sa[i-]]));
// printf("%d\n",tot);
// rep(i,1,len) printf("%s\n",&s[sa[i]]);
makesa();
// printf("!!!\n");
makeheight();
// printf("!!!\n");
// rep(i,1,len) printf("%3c",s[i]);printf("\n");
// rep(i,1,len) printf("%3d",sa[i]);printf("\n");
// rep(i,1,len) printf("%3d",rank[i]);printf("\n");
// rep(i,1,len) printf("%3d",h[i]);printf("\n");
// rep(i,1,len) printf("%3d",col[i]);printf("\n");
// rep(i,1,len) printf("%s\n",&s[sa[i]]);
rep(i,,len) h[i]=min(h[i],d[sa[i]]);
rep(i,,len) {
int j=col[sa[i]];
// printf("%d %d\n",j,i);
if (j) vec[j].push_back(i);
}
// rep(i,1,n) {
// printf("%d:%d",i,vec[i].size());
// rep(j,0,vec[i].size()-1) printf("%3d",vec[i][j]);
// printf("\n");
// }
rep(i,,len) f[][i]=h[i];
rep(i,,)
rep(j,,len-(<<i)+)
f[i][j]=min(f[i-][j],f[i-][j+(<<(i-))]);
// rep(i,0,16)
// rep(j,1,len-(1<<i)+1)
// printf("%d %d %d %d\n",i,j,j-1+(1<<i),f[i][j]);
// printf("!!\n");
rep(i,,len) num[i]=(int)floor(log(i)/log());
} int calc(int l,int r)
{
// printf("%d %d\n",l,r);
if (l>r) swap(l,r);
l++;
int i=num[r-l+];
return min(f[i][l],f[i][r+-(<<i)]);
} void ask()
{
rep(i,,m-) {
scanf("%d %d",&que[i].l,&que[i].r);
++que[i].r;
++que[i].l;
if (size[que[i].l]<size[que[i].r]) swap(que[i].l,que[i].r);
que[i].id=i;
}
sort(que,que+m,cmp);
// printf("!!\n");
// rep(i,0,m-1) printf("%d %d %d\n",que[i].l,que[i].r,que[i].id);
rep(i,,m-) {
if (i && que[i].l==que[i-].l && que[i].r==que[i-].r) ans[que[i].id]=ans[que[i-].id];
else {
int now=,x=que[i].r,y=que[i].l,last=;
rep(j,,size[x]-) {
while (now+<size[y] && vec[y][now+]<vec[x][j]) ++now;
last=max(last,calc(vec[x][j],vec[y][now]));
if (now<size[y]) last=max(last,calc(vec[x][j],vec[y][now+]));
}
ans[que[i].id]=last;
}
}
rep(i,,m-) printf("%d\n",ans[i]);
}
int main()
{
into();
ask();
return ;
}
说到底还是自己太弱,很怠惰,本来倒数第二题思路是对的一直不敢写,想想这星期除了cf就只有这一点点练习,真是的!
【hackerrank】Week of Code 30的更多相关文章
- 【hackerrank】Week of Code 26
在jxzz上发现的一个做题网站,每周都有训练题,题目质量……前三题比较水,后面好神啊,而且类型差不多,这周似乎是计数专题…… Army Game 然后给出n*m,问需要多少个小红点能全部占领 解法:乘 ...
- 【LeetCode】89.Gary Code
Problem: The gray code is a binary numeral system where two successive values differ in only one bit ...
- 【转】Visual Studio Code必备插件
先ctrl+shift+p,弹出命令面板-选中Extensions:Install Extensions 或者直接点击左侧栏这个扩展按钮(Ctrl+Shift+X) 然后左侧栏就会显示出很多插件,如图 ...
- 【HackerRank】Running Time of Quicksort
题目链接:Running Time of Quicksort Challenge In practice, how much faster is Quicksort (in-place) than I ...
- 【LeetCode】89. Gray Code
题目: The gray code is a binary numeral system where two successive values differ in only one bit. Giv ...
- 【转】Visual Studio Code 使用Git进行版本控制
原文链接:https://www.cnblogs.com/xuanhun/p/6019038.html?utm_source=tuicool&utm_medium=referral 本来认为此 ...
- 【编辑器】Visual Studio Code
1.官网:https://code.visualstudio.com/Download 2.插件:https://marketplace.visualstudio.com/VSCode https:/ ...
- 【HackerRank】How Many Substrings?
https://www.hackerrank.com/challenges/how-many-substrings/problem 题解 似乎是被毒瘤澜澜放弃做T3的一道题(因为ASDFZ有很多人做过 ...
- 【EF】EF框架 Code First Fluent API
在Code First方法中,还可以通过Fluent API的方式来处理实体与数据表之间的映射关系. 要使用Fluent API必须在构造自定义的DbContext时,重写OnModelCreatin ...
随机推荐
- MyBatis-参数处理
1.单个参数 mybatis不会做特殊处理. #{参数名/任意名}:取出参数值. 2.多个参数 mybatis会做特殊处理. 多个参数会被封装成 一个map. key:param1...paramN, ...
- 引领技术变革,腾讯云、腾讯WeTest和英特尔,合作布局云游戏
WeTest 导读 ChinaJoy作为中国泛娱乐产业年度风向标,受到全球业界的高度关注.在本届ChinaJoy上,腾讯云.腾讯WeTest和英特尔,合作为游戏玩家.游戏开发者等业界人士联合展出了云游 ...
- hdu1969Pie(根据体积二分,分馅饼)
Pie Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- python——一些常用的方法类
测试的时候经常需要使用一些方法都整理放在一起,方便调用 首先一些基本的配置引入 localReadConfig = readConfig.ReadConfig() proDir = readConfi ...
- Selenium(Python)页面对象+数据驱动测试框架
整个工程的目录结构: 常用方法类: class SeleniumMethod(object): # 封装Selenium常用方法 def __init__(self, driver): self.dr ...
- Linux管道及I/O重定向
I/O: 系统设定 默认输入设备:标准输入,STDIN,0 默认输出设备:标准输出,STDOUT,1 标准错误输出:STDERR,2 属于不同的数据流 标准输入:键盘 标准输出和错误输出:显示器 I/ ...
- Linux命令应用大词典-第19章 文件系统管理
19.1 mkfs:创建Linux文件系统 19.2 mke2fs:创建ext2.3.4文件系统 19.3 mkfs.ext4:创建ext4文件系统 19.4 mkfs.ext3:创建ext3文件系统 ...
- FU-A方式分包
当 NALU 的长度超过 MTU 时, 就必须对 NALU 单元进行分片封包. 也称为 Fragmentation Units (FUs). 0 1 2 3 0 1 2 3 4 5 6 7 8 9 ...
- PHP计算两个已知经纬度之间的距离
/** *求两个已知经纬度之间的距离,单位为千米 *@param lng1,lng2 经度 *@param lat1,lat2 纬度 *@return float 距离,单位千米 **/ privat ...
- python3 SQLAlchemy模块使用
更详细的操作介绍:https://www.imooc.com/article/22343 定义: SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对 ...