2019 Multi-University Training Contest 6

http://acm.hdu.edu.cn/contests/contest_show.php?cid=853

1002. Nonsense Time

这题比较神奇...有一个结论是:一个长度为\(n\)的随机排列的最长上升子序列期望长度为\(O(\sqrt n)\)。

那么我们考虑倒着删数,每次暴力处理出当前任意一个最长上升子序列,然后删除\(x\)的时候判一下\(x\)在不在当前的序列中,在就重新求一遍,否则不管。

由于数据随机,\(x\)在序列中的概率是\(\frac{1}{\sqrt n}\),所以期望暴力求\(\sqrt n\)次\(\rm LIS\),所以复杂度是\(O(n\sqrt n\log n)\)。

#include<bits/stdc++.h>
using namespace std; void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
} void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define pii pair<int,int >
#define vec vector<int > #define pb push_back
#define mp make_pair
#define fr first
#define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 1e6+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 1e9+7; int p[maxn],k[maxn],vis[maxn],n,in[maxn],ans[maxn],len,f[maxn]; struct tree_array {
int t[maxn];
void clear() {for(int i=1;i<=n;i++) t[i]=0;}
void modify(int x,int v) {for(;x<=n;x+=x&-x) t[x]=max(t[x],v);}
int query(int x,int ans=0) {for(;x;x-=x&-x) ans=max(ans,t[x]);return ans;}
}T; void get_lis() {
T.clear();len=0;
for(int i=1;i<=n;i++) {
in[i]=0;if(vis[i]) continue;
f[i]=T.query(p[i]-1)+1;
T.modify(p[i],f[i]);len=max(len,f[i]);
}int x=len,pre=1e9;
for(int i=n;i;i--)
if(f[i]==x&&p[i]<pre&&!vis[i]) x--,pre=p[i],in[i]=1;
// puts("OK");
// for(int i=1;i<=n;i++) printf("%d ",vis[i]);puts("");
// for(int i=1;i<=n;i++) printf("%d ",in[i]);puts("");
} void solve() {
read(n);
for(int i=1;i<=n;i++) read(p[i]);
for(int i=1;i<=n;i++) read(k[i]);
get_lis();ans[n+1]=len;
for(int i=n;i;i--) {
vis[k[i]]=1;
if(in[k[i]]) get_lis();
ans[i]=len;
}for(int i=2;i<=n+1;i++) printf("%d%c",ans[i],i==n+1?'\n':' ');
} void clear() {
for(int i=1;i<=n;i++) vis[i]=0;
} int main() {
int t;read(t);while(t--) solve(),clear();
return 0;
}

1005. Snowy Smile

这题挺无聊的,直接枚举左边界,拿一个右边界往后扫,遇到点就丢到线段树里,然后维护连续一段的和的最大值就好了。

#include<bits/stdc++.h>
using namespace std; void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
} void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double
#define ll long long #define pii pair<int,int >
#define vec vector<int > #define pb push_back
#define mp make_pair
#define fr first
#define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 4e3+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 1e9+7; struct data {int x,y,w;}a[maxn];
int n,r[maxn],lx,ly; void init() {
read(n);
for(int i=1;i<=n;i++) read(a[i].x),read(a[i].y),read(a[i].w);
for(int i=1;i<=n;i++) r[i]=a[i].x;
sort(r+1,r+n+1),lx=unique(r+1,r+n+1)-r-1;
for(int i=1;i<=n;i++) a[i].x=lower_bound(r+1,r+lx+1,a[i].x)-r;
for(int i=1;i<=n;i++) r[i]=a[i].y;
sort(r+1,r+n+1),ly=unique(r+1,r+n+1)-r-1;
for(int i=1;i<=n;i++) a[i].y=lower_bound(r+1,r+ly+1,a[i].y)-r;
} int cmp(data a,data b) {return a.x<b.x||(a.x==b.x&&a.y<b.y);} #define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1) struct segment_tree {
ll mx[maxn<<2],mxl[maxn<<2],mxr[maxn<<2],sum[maxn<<2]; void update(int p) {
mx[p]=max(mx[ls],mx[rs]);
mx[p]=max(mx[p],max(mxl[rs]+sum[ls],mxr[ls]+sum[rs]));
mx[p]=max(mx[p],mxl[rs]+mxr[ls]);
mxl[p]=max(mxl[ls],sum[ls]+mxl[rs]);
mxr[p]=max(mxr[rs],sum[rs]+mxr[ls]);
sum[p]=sum[ls]+sum[rs];
} void modify(int p,int l,int r,int x,int v) {
if(l==r) return sum[p]+=v,mxl[p]=mxr[p]=mx[p]=max(0ll,sum[p]),void();
if(x<=mid) modify(ls,l,mid,x,v);
else modify(rs,mid+1,r,x,v);
update(p);
} void clear(int p,int l,int r) {
mx[p]=mxl[p]=mxr[p]=sum[p]=0;
if(l==r) return ;
clear(ls,l,mid);clear(rs,mid+1,r);
}
}T; void solve() {
init();sort(a+1,a+n+1,cmp);int pps=1;ll ans=0;
for(int i=1;i<=lx;i++) {
T.clear(1,1,ly);while(a[pps].x!=i) pps++;
int p=pps;
for(int j=i;j<=lx;j++) {
while(a[p].x==j) T.modify(1,1,ly,a[p].y,a[p].w),p++;
ans=max(ans,T.mx[1]);
}
}printf("%lld\n",ans);
for(int i=1;i<=n;i++) a[i].x=a[i].y=a[i].w=0;
} int main() {
int t;read(t);while(t--) solve();
return 0;
}

1006. Far away

这题挺有意思的,首先我们用这\(n\)个点把平面分割成\(n^2\)个块,那么在每个块中绝对值就不会变了。

注意到\({\rm lcm}(2,3,4,5)=60\),对于每个块枚举答案横纵坐标除\(60\)的余数,然后\(O(n)\)判断合不合法,\(O(1)\)统计答案就好了。

#include<bits/stdc++.h>
using namespace std; void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
} void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define pii pair<int,int >
#define vec vector<int > #define pb push_back
#define mp make_pair
#define fr first
#define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++)
#define ll long long const int maxn = 1e2+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 1e9+7; struct data {int x,y,k,t;}a[maxn];
int lx[maxn],ly[maxn],n,m;
ll ans; int calc(int l,int r) {return l>=r?0:(r-l-1)/60+1;} int check(int x,int y) {
for(int i=1;i<=n;i++) if((abs(x-a[i].x)+abs(y-a[i].y))%a[i].k!=a[i].t) return 0;
return 1;
} void solve() {
read(n),read(m);ans=0;
for(int i=1;i<=n;i++)
read(a[i].x),lx[i]=a[i].x,read(a[i].y),ly[i]=a[i].y,read(a[i].k),read(a[i].t);
sort(lx+1,lx+n+1);
sort(ly+1,ly+n+1);
ly[n+1]=m+1,lx[n+1]=m+1;
for(int i=0;i<=n;i++) {
if(lx[i+1]-lx[i]<=0) continue;
for(int j=0;j<=n;j++) {
if(ly[j+1]-ly[j]<=0) continue;
for(int a=0;a<60;a++)
for(int b=0;b<60;b++)
if(check(lx[i]+a,ly[j]+b))
ans+=1ll*calc(lx[i]+a,lx[i+1])*calc(ly[j]+b,ly[j+1]);
}
}printf("%lld\n",ans);
} void clear() { } int main() {
int t;read(t);while(t--) solve(),clear();
return 0;
}

1008. TDL

注意到\(m\)很小,而\(f(n,m)-n\)相当于说第\(m\)小的与\(n\)互质的数,考虑到极端情况,取前\(m+\log n\)个质数也一定能取到。

所以直接暴力枚举\(f(n,m)-n\)的答案是多少,然后可以算出\(n\),得到\(n\)之后再检查一下\(f(n,m)-n\)是不是枚举的那么多。

然后对于所有\(n\)取个最小值就好了。

#include<bits/stdc++.h>
using namespace std; #define int long long void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
} void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define pii pair<int,int >
#define vec vector<int > #define pb push_back
#define mp make_pair
#define fr first
#define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 1e6+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 1e9+7; int m,k; void solve() {
read(k),read(m);int res=2e18;
for(int a=m;a<=1000;a++) {
int n=k^a,ans=0,cnt=0;
for(int i=1;i<=1000;i++) {
if(__gcd(i,n)==1) cnt++;
if(cnt==m) {ans=i;break;}
}if(a==ans) res=min(n,res);
}if(res>1e18) puts("-1");else write(res);
} signed main() {
int t;read(t);while(t--) solve();
return 0;
}

1010. Ridiculous Netizens

标算好像是玄学的树分治,但是我写了个暴力跑的比标算快\(10​\)倍....

(那就这样算了)

#include<bits/stdc++.h>
using namespace std; void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
} void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define pii pair<int,int >
#define vec vector<int > #define pb push_back
#define mp make_pair
#define fr first
#define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++)
#define iter map<int,int > :: iterator
#define for_map(i,x) for(iter i=x.begin();i!=x.end();i++) const int maxn = 3e3+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 1e9+7; int n,m,head[maxn],tot,w[maxn],ans;
struct edge{int to,nxt;}e[maxn<<1]; void ins(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot;} map<int,int > f[maxn],now[2]; void add(int &x,int y) {x+=y;if(x>=mod) x-=mod;} void dfs(int x,int fa) {
for(int i=head[x];i;i=e[i].nxt)
if(e[i].to!=fa) dfs(e[i].to,x);
int t=0;now[t][w[x]]=1;
for(int E=head[x];E;E=e[E].nxt) {
int v=e[E].to;if(v==fa) continue;
for_map(i,now[t]) {
for_map(j,f[v])
if(1ll*i->fr*j->fr<=m) {
int r=i->fr*j->fr;
add(now[t^1][r],1ll*i->sc*j->sc%mod);
} else break;
add(now[t^1][i->fr],i->sc);
}
now[t].clear();t^=1;
}f[x]=now[t];now[t].clear();
for_map(i,f[x]) add(ans,i->sc);
for(int i=head[x];i;i=e[i].nxt) f[e[i].to].clear();
} void solve() {
read(n),read(m);ans=0;
for(int i=1;i<=n;i++) read(w[i]);
for(int i=1,x,y;i<n;i++) read(x),read(y),ins(x,y),ins(y,x);
dfs(1,0);f[1].clear();write(ans);
for(int i=1;i<=n;i++) head[i]=0;tot=0;
} int main() {
int t;read(t);while(t--) solve();
return 0;
}

1012. Stay Real

全场最水的题,因为是小根堆,每次选最大的就好了。

#include<bits/stdc++.h>
using namespace std; #define int long long void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
} void print(int x) {
if(x<0) putchar('-'),x=-x;
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');} #define lf double #define pii pair<int,int >
#define vec vector<int > #define pb push_back
#define mp make_pair
#define fr first
#define sc second #define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) const int maxn = 1e6+10;
const int inf = 1e9;
const lf eps = 1e-8;
const int mod = 1e9+7; int n,t[maxn],vis[maxn]; priority_queue<pair<int,int > > q; void solve() {
read(n);
for(int i=1;i<=n;i++) vis[i/2]=1,read(t[i]);
for(int i=1;i<=n;i++) if(!vis[i]) q.push(mp(t[i],i));
int a=0,b=0;
for(int i=1;i<=n;i++) {
int x=q.top().second;q.pop();
if(x/2&&vis[x/2]) q.push(mp(t[x/2],x/2)),vis[x/2]=0;
if(i&1) a+=t[x];else b+=t[x];
}printf("%lld %lld\n",a,b);
} void clear() {
for(int i=1;i<=n;i++) vis[i]=0;
} signed main() {
int T;read(T);while(T--) solve(),clear();
return 0;
}

HDU校赛 | 2019 Multi-University Training Contest 6的更多相关文章

  1. HDU校赛 | 2019 Multi-University Training Contest 5

    2019 Multi-University Training Contest 5 http://acm.hdu.edu.cn/contests/contest_show.php?cid=852 100 ...

  2. HDU校赛 | 2019 Multi-University Training Contest 4

    2019 Multi-University Training Contest 4 http://acm.hdu.edu.cn/contests/contest_show.php?cid=851 100 ...

  3. HDU校赛 | 2019 Multi-University Training Contest 3

    2019 Multi-University Training Contest 3 http://acm.hdu.edu.cn/contests/contest_show.php?cid=850 100 ...

  4. HDU校赛 | 2019 Multi-University Training Contest 2

    2019 Multi-University Training Contest 2 http://acm.hdu.edu.cn/contests/contest_show.php?cid=849 100 ...

  5. HDU校赛 | 2019 Multi-University Training Contest 1

    2019 Multi-University Training Contest 1 http://acm.hdu.edu.cn/contests/contest_show.php?cid=848 100 ...

  6. hdu 4930 Fighting the Landlords--2014 Multi-University Training Contest 6

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4930 Fighting the Landlords Time Limit: 2000/1000 MS ...

  7. HDU 6143 - Killer Names | 2017 Multi-University Training Contest 8

    /* HDU 6143 - Killer Names [ DP ] | 2017 Multi-University Training Contest 8 题意: m个字母组成两个长为n的序列,两序列中 ...

  8. HDU 6074 - Phone Call | 2017 Multi-University Training Contest 4

    看标程的代码这么短,看我的.... 难道是静态LCA模板太长了? /* HDU 6074 - Phone Call [ LCA,并查集 ] | 2017 Multi-University Traini ...

  9. HDU 6068 - Classic Quotation | 2017 Multi-University Training Contest 4

    /* HDU 6068 - Classic Quotation [ KMP,DP ] | 2017 Multi-University Training Contest 4 题意: 给出两个字符串 S[ ...

随机推荐

  1. Python——EM(期望极大算法)教学(附详细代码与注解)

    今天,我们详细的讲一下EM算法. 前提准备 Jupyter notebook 或 Pycharm 火狐浏览器或谷歌浏览器 win7或win10电脑一台 网盘提取csv数据 需求分析 实现高斯混合模型的 ...

  2. android studio学习---Android studio 导入github工程

    无论是那种方式,都最好是先把github上的工程项目下载到本地,然后修改文件再import 首先要知道  自己的build.gradle,在project下面的版本号是多少,比如我的: depende ...

  3. VUE-v-if和v-else的使用

    1.v-if和v-else <h2 v-if="true">v-if</h2> <h2 v-else>v-else</h2> 注:v ...

  4. JVM常见面试题及答案

    11.JVM内存分哪几个区,每个区的作用是什么? java虚拟机主要分为以下一个区: 方法区:1. 有时候也成为永久代,在该区内很少发生垃圾回收,但是并不代表不发生GC,在这里进行的GC主要是对方法区 ...

  5. vmware安装后设置网络

    CentOS安装无法ping 出现Name or service not known   [root@www ~]# ping www.baidu.comping: www.baidu.com: Na ...

  6. 转: angularjs select 赋值 ng-options配置方式

    摘自: http://blog.csdn.net/chwshuang/article/details/53861249 数组方式 数据是数组 $scope.years = [2014, 2015, 2 ...

  7. 201871010128-杨丽霞《面向对象程序设计(java)》第四周学习总结

    201871010128-杨丽霞<面向对象程序设计(java)>第四周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh 这个 ...

  8. ubuntu配置定时任务crontab何保存退出

    crontab -e配置完成后,如何把保存并退出? 1.Ctrl+o 写入 2.出现“FIile name to Write...”,输入Enter 3.Ctrl+x 保存输出 提示“crontab: ...

  9. python基础之函数重点

    函数的返回值 现在有一个需求,比较两个人的月薪,然后想获取月薪较大人的年薪. 如果需要在程序中拿到函数的处理结果做进一步的处理,则需要函数必须要有返回值. 需要注意的是: return是一个函数结束的 ...

  10. Java的修饰、继承、接口、抽象类

     1.private 修饰属性或者方法,只能在本类中被访问,定义后需要加get()set()方法,这样提高数据的安全性 私有属性虽然不能直接访问,但是其对象 或者 子类对象可以通过公有方法进行设值和获 ...