csp-s模拟99题解

题面:https://www.cnblogs.com/Juve/articles/11791219.html

上来先看T1,发现和之前做过的treap一样,是线段树维护单调栈,然后打了一个小时,然后它挂了

于是看后面的题,然后T2:woc它说的是什么?怎么这么多变量?貌似k=2可以大力分类讨论?

写了半个小时,发现恶心至极,然后puts("-1")就跑了

T3好像有暴力?打了个搜索,一遍过样例,应该有40分了吧,在加上T1暴力就60分了

突然发现T1可以分块直接艹过,果断分块,然后过样例,对拍出锅,

对拍发现了4出错误,然后改完了发现我的分块会被卡成n方?

如果是一个单增的序列,然后他要修改一个特别靠前的位置,我就成n2了,但是这种数据倒也跑的挺快,只是对拍不过

最后半个小时,检查了一下文件名,然后T3本着骗分的原则我按a+b排序从大到小输出

然后改了改T1,发现它过拍了,然后就这样了,一直到考试结束,感觉T1可能会被卡

期望得分:80+10+30=120

实际得分:100+10+100=210!!??

T3不是正解居然A了。。。我rp估计要掉光了,然后T1没有被卡??!!

其实$nlog^2n$和$n\sqrt{n}$复杂度差不多,卡我时间还是挺难的,虽说正解只有一个log,但是常数没有分块优秀

T1:

说是分块其实就是优化的暴力

预处理原序列的前缀答案,前缀最大值,块内最值,

那么每次修改对于前面的答案没有影响,直接接过来,然后在本块中跑暴力,把修改位置所在块的贡献加上,同时记录到当前块的最大值

然后扫后面的块,如果块内最大值比当前最大值小,那么这个块没有用,反之就暴力更新块内的答案

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 #define re register
  7 using namespace std;
  8 const int MAXN=1e5+5;
  9 inline int read(){
 10     re int x=0,f=1;re char ch=getchar();
 11     while(ch<‘0‘||ch>‘9‘){
 12         if(ch==‘-‘) f=-1;
 13         ch=getchar();
 14     }
 15     while(ch>=‘0‘&&ch<=‘9‘){
 16         x=(x<<3)+(x<<1)+ch-‘0‘;
 17         ch=getchar();
 18     }
 19     return x*f;
 20 }
 21 int n,m,a[MAXN],pos[MAXN],b[MAXN],d[MAXN],maxx=0;
 22 int blo,bel[MAXN],l[MAXN],r[MAXN],tot,mx[MAXN],len[MAXN],fmx[MAXN],smx[MAXN],p[MAXN];
 23 signed main(){
 24     freopen("TaoPApp.in","r",stdin);
 25     freopen("TaoPApp.out","w",stdout);
 26     n=read(),m=read();
 27     blo=sqrt(n)+1;
 28     tot=n/blo;
 29     if(n%blo) ++tot;
 30     for(re int i=1;i<=n;++i){
 31         a[i]=read();
 32         bel[i]=(i-1)/blo+1;
 33     }
 34     for(re int i=1;i<=tot;++i){
 35         l[i]=r[i-1]+1;
 36         r[i]=i*blo;
 37     }
 38     r[tot]=min(r[tot],n);
 39     for(re int i=1;i<=tot;++i){
 40         for(re int j=l[i];j<=r[i];++j){
 41             if(fmx[i]<=a[j]){
 42                 fmx[i]=a[j];
 43                 p[i]=j;
 44             }
 45         }
 46         for(re int j=l[i];j<=r[i];++j){
 47             if(j!=p[i]&&smx[i]<=a[j]){
 48                 smx[i]=a[j];
 49             }
 50         }
 51     }
 52     for(re int i=1;i<=n;++i){
 53         mx[i]=max(mx[i-1],a[i]);
 54         len[i]=len[i-1];
 55         if(maxx<a[i]){
 56             maxx=a[i];
 57             ++len[i];
 58         }
 59     }
 60     for(re int i=1;i<=m;++i){
 61         pos[i]=read(),b[i]=read();
 62         re int tmp=a[pos[i]];
 63         a[pos[i]]=b[i];
 64         re int c=bel[pos[i]];//当前块
 65         re int res=len[l[c]-1];//当前块前的答案
 66         re int zd=mx[l[c]-1];//上一个块前的最大值
 67         for(re int j=l[c];j<=r[c];++j){
 68             if(zd<a[j]){
 69                 zd=a[j];
 70                 ++res;
 71             }
 72         }
 73         if(pos[i]!=p[c]){
 74             for(re int j=c+1;j<=tot;++j){
 75                 if(mx[r[j]]<=zd) continue;
 76                 for(re int k=l[j];k<=r[j];++k){
 77                     //++tot;
 78                     if(zd<a[k]){
 79                         zd=a[k];
 80                         ++res;
 81                     }
 82                 }
 83                 res+=len[n]-len[r[j]];
 84                 break;
 85             }
 86             printf("%d\n",res);
 87             a[pos[i]]=tmp;
 88         }else{
 89             re int tmpp=max(zd,smx[c]);
 90             tmpp=max(tmpp,b[i]);
 91             for(re int j=c+1;j<=tot;++j){
 92                 if(fmx[j]<=tmpp) continue;
 93                 for(re int k=l[j];k<=r[j];++k){
 94                     if(tmpp<a[k]){
 95                         tmpp=a[k];
 96                         ++res;
 97                     }
 98                 }
 99             }
100             printf("%d\n",res);
101             a[pos[i]]=tmp;
102         }
103     }
104     return 0;
105 }
106 /*
107 5 3
108 1 2 3 4 4
109 1 5
110 5 5
111 2 3
112 */

T2:

贪心+模拟

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<set>
 6 #define int long long
 7 using namespace std;
 8 const int MAXN=5e4+5;
 9 inline int read(){
10     int x=0,f=1;char ch=getchar();
11     while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1;ch=getchar();}
12     while(ch>=‘0‘&&ch<=‘9‘){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();}
13     return x*f;
14 }
15 int k,c[MAXN],d[MAXN],m[MAXN],p[MAXN],e[MAXN],r[MAXN],E[MAXN],cst,tot=0,ans=0;
16 struct node{
17     int num,cost;
18     friend bool operator < (node a,node b){
19         return a.cost<b.cost;
20     }
21 };
22 multiset<node>s1,s2;
23 signed main(){
24     freopen("happy.in","r",stdin);
25     freopen("happy.out","w",stdout);
26     k=read();
27     for(int i=1;i<=k;++i) c[i]=read(),d[i]=read(),m[i]=read(),p[i]=read();
28     for(int i=1;i<k;++i) e[i]=read(),r[i]=read(),E[i]=read();
29     cst=c[1];
30     for(int i=1;i<=k;++i){
31         if(p[i]) s1.insert((node){p[i],m[i]+cst});
32         tot+=p[i];
33         while(d[i]){
34             if(s1.empty()){
35                 puts("-1");
36                 return 0;
37             }
38             node x=*s1.begin();
39             int num=min(d[i],x.num);
40             s1.erase(s1.begin());
41             ans+=x.cost*num;
42             x.num-=num,tot-=num,d[i]-=num;
43             if(x.num) s1.insert(x);
44         }
45         if(i!=k){
46             cst=min(cst+r[i],c[i+1]);
47             while(tot>e[i]){
48                 node x=*--s1.end();
49                 int num=min(tot-e[i],x.num);
50                 s1.erase(--s1.end());
51                 tot-=num,x.num-=num;
52                 if(x.num) s1.insert(x);
53             }
54             for(multiset<node>::iterator it=s1.begin();it!=s1.end();++it){
55                 s2.insert((node){(*it).num,(*it).cost+E[i]});
56             }
57             swap(s1,s2),s2.clear();
58         }
59     }
60     printf("%lld\n",ans);
61     return 0;
62 }

T3:

按a排序,保留最大的A,然后在剩下的里面两两分组,组内取b较大的

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define int long long
 6 using namespace std;
 7 const int MAXN=4e5+5;
 8 int n;
 9 struct node{
10     int a,b,id;
11     friend bool operator < (node aa,node bb){
12         return aa.a==bb.a?aa.b>bb.b:aa.a>bb.a;
13     }
14 }p[MAXN];
15 signed main(){
16     freopen("grandmaster.in","r",stdin);
17     freopen("grandmaster.out","w",stdout);
18     scanf("%lld",&n);
19     for(int i=1;i<=2*n+1;++i){
20         scanf("%lld%lld",&p[i].a,&p[i].b);
21         p[i].id=i;
22     }
23     sort(p+1,p+2*n+1+1);
24     printf("%lld\n",p[1].id);
25     for(int i=2;i<=2*n+1;i+=2){
26         if(p[i].b>p[i+1].b){
27             printf("%lld\n",p[i].id);
28         }
29         else printf("%lld\n",p[i+1].id);
30     }
31     return 0;
32 }

原文地址:https://www.cnblogs.com/Juve/p/11791336.html

时间: 2024-10-09 07:21:28

csp-s模拟99题解的相关文章

HDU 1022 Train Problem I 模拟栈题解

火车进站,模拟一个栈的操作,额外的栈操作,查看是否能按照规定顺序出栈. 数据量很少,故此题目很容易AC. 直接使用数组模拟就好. #include <stdio.h> const int MAX_N = 10; char inOrder[MAX_N], outOrder[MAX_N], stk[MAX_N]; bool rs[MAX_N<<2]; int n; int main() { while (scanf("%d", &n) != EOF) { s

10-4国庆节第七场模拟赛题解

10-4 国庆节第七场模拟赛题解 T1工厂 (factory) 水 #include<iostream> #include<cstdio> #define int long long using namespace std; inline int read(){ int sum=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); } while(ch>='0

2018-10-25 模拟测试题解

目录 问题 A: 魏传之长坂逆袭 题目描述 输入 输出 样例输入 样例输出 题解 问题 B: 蜀传之单刀赴会 题目描述 [问题描述] 输入 输出 样例输入 样例输出 题解 问题 C: 吴传之火烧连营 [题目背景] [问题描述] 输入 输出 样例输入 样例输出 [样例解释] [数据规模和约定] 题解 本篇题解也发表于zwcblog作者是同一个人 问题 A: 魏传之长坂逆袭 题目描述 众所周知,刘备在长坂坡上与他的一众将领各种开挂,硬生生从曹操手中逃了出去,随后与孙权一起火烧赤壁.占有荆益.成就霸业

10月15日模拟赛题解

10月15日模拟赛题解 A 树 Description 给定一棵 \(n\) 个节点的树,每个节点有两个参数 \(a,~b\),对于每个节点,求子树中参数为 \(b\) 的所有节点的 \(a\) 之和 Limitations \(100\%\) \(1 \leq b \leq n \leq 10^5,~a \leq 1000\) \(60\%\) \(1 \leq b,n\leq 1000\) \(30\%\) \(1 \leq b, n \leq 10\) Solution 对于 \(30\%

lzoi模拟赛题解

A题:签到题原题:mtoi 联赛 的A题定位:真.签到题(普及B题或者提高d1A题)考点:选手的基本数学能力思维难度:提高-代码难度:普及A题 题解:80%:暴力枚举100%:注意到(a xor b)<=(a+b),于是把所有的数异或起来即可. B题:送分题原题:[多省省队联测]d2A:皮配定位:一道联赛d1B题,考察了选手的基本功.送了选手70分.把70%的2种做法扩展可以得到正解考点:多种背包dp,计数思维难度:提高代码难度:提高+ 前面的几个数据可以暴力枚举解决.50%的数据:考虑dp.设

计蒜课 八月模拟赛题解

看见机房有大佬上周写了上面的普及信心赛 于是我康了康 8月的提高组模拟赛 9月的还没开始qwq 真的 有点难 主要是我先打开了T2 我再次 对自己的数学产生了怀疑 我现在还是不会写T2 T1 又又又又都错题了 下次重建图 尽量写vector 都写 邻接表 变量差不多的容易搞混 我这个同学变又写错了 T1 :https://nanti.jisuanke.com/t/41086 题目大意就是 一个有向图 删一个点 把与他直接和间接 相连的点 删掉 然后 求删掉所有点的最小最大代价 : 为了避免这个环

考试总结 模拟99

考试过程 最后一场两位数的考试,死的很惨 开题后T1看了一眼,第一眼觉得是最长上升子序列,线性dp的那种 然后就去刚O(n)的算法,不久就听到大多数人敲键盘的声音,比较着急, 尤其是旁边人自信满满的动作....然后就通过写暴力稳定心态.写完之后没试样例就继续想 思考效率指数级降低...想要对旁边人予以“反击”,可还是没有思路 1h多后有看题发现样例过不了,虽然之前先看了一眼样例但是并不能把握每一个细节 又读了半天题最终在打算弃掉T1前读懂了... 浪费了1h30min??顿时一股来自西西伯利亚的

省选模拟6 题解

A. Yist 首先考虑怎样的情况答案是不收敛的. 操作中涉及到对一个权值非$0$,并且不作除法的点的加法贡献. 因为只要最终的答案,可以想到对每个点作为出边的贡献分别处理. 部分分提示求出第一次迭代的贡献,发现对于每个点,贡献都是一个等比数列,所以只要代入求和公式就好了. 然而暴力做的复杂度是$O(mk)$的,会被菊花图的数据卡掉. 考虑如何优化这个东西,根据套路我们将点按照度数分块. 定义度数大于$\sqrt m$的点为重点,度数小于等于$\sqrt m$的点为轻点. 分别讨论: 对于对轻点

省选模拟七 题解

写在前面: 这次考试的策略还是蛮正确的 发现了$T2$是水题后先开了$T3$的$60pts$暴力 剩下时间连打带调外加考场刚好用完时间 但可惜的是$T1dp$求两点之间最小代价由于转移出环被弃掉了 其实用$bfs$求最小代价就可以$AC$了 实力不济 就没什么好说的 A. 翻转硬币 标签: $bfs+$状压$dp$ 题解: 先对序列差分 问题转化为每次可以同时异或两个点,求最小代价 同时消去两个点的代价可以用$bfs$预处理出来 源点的个数就是差分序列的$1$的个数 有了这个,状态便有了明显的层