A - Messenger Simulator

CodeForces - 1288E

两种解法,我选择了第二种

mn很好求,联系过就是1,没联系过就是初始位置

第一种:统计同一个人两次联系之间的出现的不同的人的个数,这个值用来更新mx[i],模拟一下就可以理解。而在第一次联系之前的部分,由于初始是顺序的,所以只需要统计i第一次联系之前出现的大于i的不同的人的个数,用这个数字和初始位置之和来更新mx[i]。对于最后一次联系之后的部分,我们可以假定在m+1的位置再次与其进行联系,然后套用前面两次联系之间的情况即可,需要注意的是对于所有的i都是假设在m+1的位置再次进行联系。对于从来都没有联系过的人,同样假设m+1联系并套用第一次联系之前的模式即可,其实也就是整个序列m中比i大的不同人的个数是多少。复杂度在统计两次联系之间那里,可以用莫队或者主席树实现,其他部分可以用树状数组实现。

第二种就是模拟这个过程,初始位置对应线段树m+1~m+n区间,每次练习就是把一个人当前位置对应权值-1,然后在最前面+1,容易发现只需要统计每次联系前的位置即可(仍视为m+1次联系了所有的i,其实就是在全部联系结束之后再次统计当前位置)。

 #include<bits/stdc++.h>
#define LL long long
#define dl double
using namespace std;
const int inf=3e5+;
int n,m;
int mn[inf],mx[inf];
int f[inf<<];
int fir,hs[inf];
#define mid (l+r>>1)
#define rs (o<<1|1)
#define ls (o<<1)
void add(int o,int l,int r,int x,int y){
if(l == r){f[o]+=y;return ;}
if(x <= mid)add(ls,l,mid,x,y);
else add(rs,mid+,r,x,y);
f[o]=f[ls]+f[rs];
}
int query(int o,int l,int r,int x){
if(r <= x)return f[o];
if(x <= mid)return query(ls,l,mid,x);
else return f[ls]+query(rs,mid+,r,x);
}
int main(){
// freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);fir=m;
for(int i=;i<=n;i++)add(,,n+m,hs[i]=i+m,),mx[i]=mn[i]=i;
for(int i=;i<=m;i++){
int x;scanf("%d",&x);
mx[x]=max(mx[x],query(,,n+m,hs[x]));
add(,,n+m,hs[x],-);
add(,,n+m,hs[x]=fir--,);
mn[x]=;
}
for(int i=;i<=n;i++)mx[i]=max(mx[i],query(,,n+m,hs[i]));
for(int i=;i<=n;i++)printf("%d %d\n",mn[i],mx[i]);
return ;
}

B - Restore Permutation

CodeForces - 1208D

此题很容易想到从后往前处理。最后一个可以直接算出来,然后排除他的影响,算倒数第二个....我们需要证明一个结论,对于当前处理的位置(排除了已经用过的),s[i]严格单调,此结论很容易证明,任取i<j即可发现s[i]<s[j]。我开了一个set储存当前剩余的元素,set内比较的是其在当前位置时对应的s[i],然后lower_bound即可找到答案,nlog^2。

标答1的解法是:每次寻找s[i]为0的点,最右面的这种点便是1(他的右面不可能有0了),然后把他后面的s[i]都-1,再找2,重复此过程。

标答2是树状数组做法,同样倒序处理,巧妙运用树状数组免去了二分的麻烦同时省去了"删除操作",也就把我的set直接去掉了。

 #include<bits/stdc++.h>
#define LL long long
#define dl double
using namespace std;
const int inf=2e5+;
int n;
LL s[inf];
LL f[inf];
int a[inf];
int lowbit(int x){return x&(-x);}
LL sum(int x){LL ans=;for(int i=x;i;i-=lowbit(i))ans+=f[i];return ans;}
void add(int x){for(int i=x;i<=n;i+=lowbit(i))f[i]+=x;}
struct ghb{
int id;
LL val;
bool operator < (const ghb &o)const{
LL tp1=1ll*id*(id-)/-sum(id),tp2=1ll*o.id*(o.id-)/-sum(o.id);
if(!o.id)tp2=o.val;
return tp1 < tp2;
}
};
set<ghb>S;
set<ghb>::iterator g;
int main(){
// freopen("in.txt","r",stdin);
scanf("%d",&n);
for(int i=;i<=n;i++)scanf("%lld",&s[i]),S.insert((ghb){i,});
for(int i=n;i>=;i--){
g=S.lower_bound((ghb){,s[i]});
a[i]=(*g).id;add((*g).id);S.erase(g);
}
for(int i=;i<=n;i++)printf("%d ",a[i]);
return ;
}

C - Turing Tree

HDU - 3333

莫队的模板题

或者还有两种解法

第一种:主席树,在线算法,每个位置记录对应数值上一次出现的位置,然后变成了区间查询小于l的元素个数的问题,只不过是把权值1变成了对应数的数值。

另一种:线段树/树状数组,离线算法,把询问按右节点排序,依次插入每一个数,在树状数组中加上对应值,如果这个数之前出现过,那么把之前的减去对应值。

 #include<bits/stdc++.h>
#define LL long long
#define dl double
using namespace std;
const int inf=3e4+;
int T;
int n,m;
struct ghb{
int id,val1,val2;
bool operator < (const ghb &o)const{return val1 < o.val1;}
}a[inf];
bool cmp1(ghb &a,ghb &b){return a.id < b.id;}
int bel[inf];
struct Query{
int l,r,id;
LL ans;
bool operator < (const Query &o)const{return bel[l] == bel[o.l] ? r<o.r : bel[l]<bel[o.l];}
}q[inf<<];
bool cmp2(Query &a,Query &b){return a.id < b.id;}
int cnt[inf];
void work(){
LL ans=;
int l=,r=;
for(int i=;i<=m;i++){
while(l < q[i].l){
cnt[a[l].val2]--;
if(cnt[a[l].val2] == )ans-=a[l].val1;
l++;
}
while(l > q[i].l){
l--;
cnt[a[l].val2]++;
if(cnt[a[l].val2] == )ans+=a[l].val1;
}
while(r < q[i].r){
r++;
cnt[a[r].val2]++;
if(cnt[a[r].val2] == )ans+=a[r].val1;
}
while(r > q[i].r){
cnt[a[r].val2]--;
if(cnt[a[r].val2] == )ans-=a[r].val1;
r--;
}
q[i].ans=ans;
}
}
int main(){
// freopen("in.txt","r",stdin);
scanf("%d",&T);
a[].val1=-;
while(T--){
memset(cnt,,sizeof(cnt));
scanf("%d",&n);int len=sqrt(n);
for(int i=;i<=n;i++)scanf("%d",&a[i].val1),bel[a[i].id=i]=(i-)/len+;
sort(a+,a+n+);
for(int i=;i<=n;i++)a[i].val2=a[i].val1 == a[i-].val1 ? a[i-].val2 : a[i-].val2+;
sort(a+,a+n+,cmp1);
scanf("%d",&m);
for(int i=;i<=m;i++)scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
sort(q+,q+m+);
work();
sort(q+,q+m+,cmp2);
for(int i=;i<=m;i++)printf("%lld\n",q[i].ans);
}
return ;
}
/*莫队模板题*/

D - Welfare State

CodeForces - 1199D

第一感觉就是线段树模拟这个过程,因为只有一次询问所以也不是吉司机那种,然后写的过程中发现有些累赘,感觉有更简单的方法。

其实可以用O(n)的做法,只要倒序枚举所有操作并记录2操作最大值,在某个位置的1操作第一次被枚举到的时候更新当前点的值即可,同样,从来没被1操作过的可以视为在0处有一个1操作,也就是全枚举完后对没被1操作过的位置取一个max。

只有线段树的代码

 #include<bits/stdc++.h>
#define LL long long
#define dl double
using namespace std;
const int inf=2e5+;
int n,q;
int f[inf<<],tag[inf<<];
#define ls (o<<1)
#define rs (o<<1|1)
#define mid (l+r>>1)
void tagdown(int o){
tag[ls]=max(tag[ls],tag[o]);
tag[rs]=max(tag[rs],tag[o]);
tag[o]=;
}
void modify(int o,int l,int r,int x,int y){
if(l == r){tag[o]=;f[o]=y;return ;}
tagdown(o);
if(x <= mid)modify(ls,l,mid,x,y);
else modify(rs,mid+,r,x,y);
}
void out(int o,int l,int r){
if(l == r){printf("%d ",max(f[o],tag[o]));return ;}
tagdown(o);out(ls,l,mid);out(rs,mid+,r);
}
int main(){
// freopen("in.txt","r",stdin);
scanf("%d",&n);
for(int i=;i<=n;i++){int x;scanf("%d",&x);modify(,,n,i,x);}
scanf("%d",&q);
for(int i=;i<=q;i++){
int x,y,z;scanf("%d%d",&x,&y);
if(x == ){scanf("%d",&z);modify(,,n,y,z);}
else tag[]=max(tag[],y);
}
out(,,n);
return ;
}
/*又是一道伪吉司机线段树,因为只有一次询问所以很简单*/
/*似乎压根不存在f的转移,应该可以用更简洁的方法做出来*/

E - Playlist

CodeForces - 1140C

道理很简单,按b从大到小排序,顺序枚举选择前k大。然而我选择了很愚蠢的二分+树状数组来求前k大,事实上一个优先队列就可以轻松解决。

 #include<bits/stdc++.h>
#define LL long long
#define dl double
using namespace std;
const int inf=3e5+;
int n,k;
struct Song{
int t,b;
bool operator < (const Song &o)const{
return b > o.b;
}
}a[inf];
int lowbit(int x){return x&(-x);}
int f1[inf<<];
LL f2[inf<<];
void add(int x){int y=1e6-x+;for(int i=y;i<=1e6;i+=lowbit(i))f1[i]++,f2[i]+=x;}
int sum1(int x){int ans=;for(int i=x;i;i-=lowbit(i))ans+=f1[i];return ans;}
LL sum2(int x){LL ans=;for(int i=x;i;i-=lowbit(i))ans+=f2[i];return ans;}
LL ANS;
int main(){
// freopen("in.txt","r",stdin);
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++)scanf("%d%d",&a[i].t,&a[i].b);
sort(a+,a+n+);
for(int i=;i<=n;i++){
add(a[i].t);
int l1=,r1=1e6;
while(l1 != r1){
int mid=(l1+r1>>)+;
if(sum1(mid) > k)r1=mid-;
else l1=mid;
}
int l2=,r2=1e6;
while(l2 != r2){
int mid=l2+r2>>;
if(sum1(mid) < k)l2=mid+;
else r2=mid;
}
LL ans=sum2(l1);
int tp1=sum1(l1);
if(tp1 < k && sum1(l2) > k)ans+=1ll*(1e6-l2+)*(k-tp1);
ANS=max(ANS,ans*a[i].b);
}
printf("%lld\n",ANS);
return ;
}
/*二分+树状数组实现前k大?*/

CSU-ACM2020寒假集训比赛2的更多相关文章

  1. CSU-ACM寒假集训选拔-入门题

    CSU-ACM寒假集训选拔-入门题 仅选择部分有价值的题 J(2165): 时间旅行 Description 假设 Bobo 位于时间轴(数轴)上 t0 点,他要使用时间机器回到区间 (0, h] 中 ...

  2. 洛谷2018寒假集训tg第二次比赛第二题Princess Principal题解

    这算不算泄题啊...被kkk发现会咕咕咕吧. 题目大意:给定一个数列a,与常数n,m,k然后有m个询问,每个询问给定l,r.问在a[l]到a[r]中最少分成几段,使每段的和不超过k,如果无解,输出Ch ...

  3. 中南大学2019年ACM寒假集训前期训练题集(基础题)

    先写一部分,持续到更新完. A: 寒衣调 Description 男从戎,女守家.一夜,狼烟四起,男战死沙场.从此一道黄泉,两地离别.最后,女终于在等待中老去逝去.逝去的最后是换尽一生等到的相逢和团圆 ...

  4. 中南大学2019年ACM寒假集训前期训练题集(入门题)

    A: 漫无止境的八月 Description 又双叒叕开始漫无止境的八月了,阿虚突然问起长门在这些循环中团长哪几次扎起了马尾,他有多少次抓住了蝉等等问题,长门一共回复n个自然数,每个数均不超过1500 ...

  5. 2022寒假集训day2

    day1:学习seach和回溯,初步了解. day2:深度优化搜索 T1 洛谷P157:https://www.luogu.com.cn/problem/P1157 题目描述 排列与组合是常用的数学方 ...

  6. 今年暑假不AC - HZNU寒假集训

    今年暑假不AC "今年暑假不AC?" "是的." "那你干什么呢?" "看世界杯呀,笨蛋!" "@#$%^&a ...

  7. 【寒假集训系列DAY.1】

    Problem A. String Master(master.c/cpp/pas) 题目描述 所谓最长公共子串,比如串 A:“abcde”,串 B:“jcdkl”,则它们的最长公共子串为串 “cd” ...

  8. GlitchBot -HZNU寒假集训

    One of our delivery robots is malfunctioning! The job of the robot is simple; it should follow a lis ...

  9. Wooden Sticks -HZNU寒假集训

    Wooden Sticks There is a pile of n wooden sticks. The length and weight of each stick are known in a ...

随机推荐

  1. css实现单行居中,两行居左

    居中需要用到 text-align:center,居左是默认值也就是text-align:left.要让两者结合起来需要多一个标签. <h2><p>单行居中,多行居左</ ...

  2. Js 获取当前日期时间及其它操作(转)

    Js获取当前日期时间及其它操作 var myDate = new Date();myDate.getYear();        //获取当前年份(2位)myDate.getFullYear();   ...

  3. storm的JavaAPI运行报错

    报错:java.lang.NoClassDefFoundError: org/apache/storm/topology/IRichSpout 原因:idea的bug:本地运行时设置scope为pro ...

  4. 十六、JSONObject与JSONArray使用-不刷新页面做回写显示

    需要导入:json-lib-2.2.2-.jar包 1.json:就是一个键对应一个值,超级简单的一对一关系.对于json嵌套,只要记住符号“:”前是键,符号后是值大括号成对找. String arr ...

  5. Linux centosVMware yum更换国内仓库源、yum下载rpm包、源码包安装

    一.yum更换国内仓库源 cd /etc/yum.repos.d/ rm -f dvd.repo wget http://mirrors.163.com/.help/CentOS7-Base-163. ...

  6. 2017北京网络赛 J Pangu and Stones 区间DP(石子归并)

    #1636 : Pangu and Stones 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 In Chinese mythology, Pangu is the fi ...

  7. IDEA自用插件,驼峰插件,MyBatis插件,Lombok插件

    IDEA自用插件 驼峰插件:CamelCase,Shift + Alt + u快速切换驼峰 MyBatisX插件:快速在mapper之间跳转 Lombok插件:注解实现get.set方法 MyBati ...

  8. 一个小证明(题解 P5425 Part1)

    所以这道题为什么可以这样做 嗯,我也不知道,不过我是来填坑的. \(Q\):为什么要把牛分成\(1\),\(1\)......\(N-K+1\)这样的\(K\)组呢? \(A\):我们设第\(i\)组 ...

  9. loadBeanDefinitions方法源码跟踪(二)

    因为字数超过了限制,所以分成了三篇,承接上篇: https://www.jianshu.com/p/a0cfaedf3fc5 代码过宽,可以shift + 鼠标滚轮 左右滑动查看 3.parseDef ...

  10. input type="submit" 和"button"有什么区别

    HTML中<input type="submit" /> 和 <input type="button" /> 主要从元素定义类型.点击触 ...