今天这个成绩还是不怎么理想,没能A掉T1,实乃一大遗憾

T1:盘王节

其实这道题没什么思维难度,主要就是注意细节。

进攻有 2 2 2种情况:

1. 1. 1.先全部打御符,用尽量小的去打,即大于等于它最小的那个,打完后,只剩兵符,此时有又有 2 2 2种选择,若兵符大于 0 0 0则产生负贡献,就直接把它看做 0 0 0,若它小于 0 0 0且小于攻击的兵符,则产生正贡献,就打兵符。

2. 2. 2.贪心打兵符(不存在边打兵符,边打御符,若要打御符,还不如先打完) 用最大的攻击兵符去打最小的,这样会产生更大的贡献。

考场思路:由绝对值小于等于 100 100 100变相想到用桶来储存,先 s o r t sort sort,再 u n i q u e unique unique一下,接下来 l o w e r lower lower_ b o u n d bound bound查找,但这样极大地增加了时间的复杂度,而且我打完御符后就没打负的兵符了,贪心时也有部分细节没注意,望改进。

反思:

  1. 过于信任大样例,没有仔细检查;
  2. 思路不严密,问题想了一半就走人了

做题和人生都是这样

不要妄自菲薄也不要盲目自信

要看到希望却又不忘记安危(来自 F s y Fsy Fsy巨佬的鸡汤)

代码:

#include<bits/stdc++.h>
#define int long long
#define db double
#define re register
#define cs const
#define N 1000005
using namespace std;
inline int read()
{int x=0,f=1;char ch;while(ch>'9'||ch<'0'){if(ch=='-')  f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return f*x;
}
struct node
{int num,val;bool operator < (cs node &a) cs{return val<a.val;}
}a[N],b[N],c[N],d[N],e[N],f[N];
int n,m1,m2,ans,sum;
bool mark;
void work()
{int j=n;for(re int i=1;i<=m2;++i){while(j&&c[i].num>a[j].num&&c[i].val<=a[j].val){sum+=(a[j].val-c[i].val)*a[j].num;c[i].num-=a[j].num;a[j].num=0;--j;}if(!j||c[i].val>a[j].val) break;sum+=(a[j].val-c[i].val)*c[i].num;a[j].num-=c[i].num;c[i].num=0;}ans=max(ans,sum);
}
void work2()
{int j=1;sum=0;for(re int i=1;i<=m1;++i){while(j<n&&a[j].val<b[i].val)   ++j;while(j<n&&b[i].num>a[j].num&&b[i].val<=a[j].val){b[i].num-=a[j].num;a[j].num=0;++j;}if(b[i].val>a[j].val){mark=1;break;}   a[j].num-=b[i].num;b[i].num=0;if(j==n&&!a[j].num){mark=1;break;}}j=n;for(int i=1;i<=m2;++i){if(c[i].val>=0)    break;while(j&&c[i].num>a[j].num&&c[i].val<=a[j].val){sum+=(a[j].val-c[i].val)*a[j].num;c[i].num-=a[j].num;a[j].num=0;--j;}if(!j||c[i].val>a[j].val)  break;sum+=(a[j].val-c[i].val)*c[i].num;a[j].num-=c[i].num;c[i].num=0;}if(!mark)    for(re int i=1;i<=n;++i) if(a[i].val>0)   sum+=a[i].val*a[i].num;ans=max(ans,sum);
}
signed main()
{n=read();m1=read();m2=read();for(re int i=1;i<=n;++i)    a[i].val=read(),a[i].num=read();for(re int i=1;i<=m1;++i)  b[i].val=read(),b[i].num=read();for(re int i=1;i<=m2;++i)  c[i].val=read(),c[i].num=read();      sort(a+1,a+1+n);sort(b+1,b+1+m1);sort(c+1,c+1+m2);for(re int i=1;i<=n;++i)  d[i]=a[i];for(re int i=1;i<=m1;++i) e[i]=b[i];for(re int i=1;i<=m2;++i) f[i]=c[i];work();swap(a,d),swap(b,e),swap(c,f);work2();printf("%lld",ans);return 0;
}

T2:祝著节

题意:给你一个联通的无向图,找出所有权值和大于等于 X X X的最(次)小生成树的方案数,且树内必须至少有 2 2 2条边颜色不同,且最小的权值和必须等于 X X X。

思路:(部分内容来自 w y h wyh wyh巨佬 o r z orz orz)

首先有一个结论必须推出:我们得到的所有方案中的最小生成树与原图中最小生成树的形态有且仅有一条边不同。

证明:假设已求出一棵纯色的最小生成树,我们加入一条另外一种颜色的树外边,并拆掉构成的环中最大的那条边,此时方案已经合法,若我们再去加边拆边,则无意义。

接着,对于每条非树边,我们求出强制包含其的不严格次小生成树,利用树上倍增来求(需熟练掌握),环上减去最大边即可。

对于次小生成树的权值,分两种情况讨论。

如果该次小生成树权值等于 X X X,记为 e q u + + equ++ equ++。如果小于,记为 l e s + + les++ les++,大于不管。

然后对于最初的 s u m sum sum,也要讨论。

如果最初的 s u m sum sum已经等于 X X X,那新加的边也只能是 e q u equ equ。

根据刚刚结论,有 n − 1 n-1 n−1条最小生成树边同色,而剩下的边中,有 e q u equ equ条边,这些边不能全都和 M S T MST MST同色。

容斥一下,总方案减去非法方案(即 e q u + n − 1 equ+n-1 equ+n−1条边都同色),得到

A n s = 2 m − 2 ∗ ( 2 m − ( n − 1 ) − e q u ) A n s=2^{m}-2 *\left(2^{m-(n-1)-e q u}\right) Ans=2m−2∗(2m−(n−1)−equ)

这个 2 2 2是因为颜色可以同时取反。

如果 s u m sum sum小于 X X X,那我们在取能使答案合法的 e q u equ equ的同时,那些 l e s les les边都要和 M S T MST MST同色,否则答案不会取 e q u equ equ。

使用容斥, A n s = 2 ∗ ( 2 m − ( n − 1 ) − l e s − 2 m − ( n − 1 ) − l e s − e q u ) A n s=2 *\left(2^{m-(n-1)-l e s}-2^{m-(n-1)-l e s-e q u}\right) Ans=2∗(2m−(n−1)−les−2m−(n−1)−les−equ)

即可得出答案。

代码:

#include<bits/stdc++.h>
#define int long long
#define db double
#define re register
#define cs const
#define mod 1000000007
#define N 200003
using namespace std;
inline int read()
{int x=0,f=1;char ch;while(ch>'9'||ch<'0'){if(ch=='-')  f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return f*x;
}
struct node
{int from,to,w,flag;bool operator < (cs node &a)cs{return w<a.w;}
}edge[N];
int first[N],equ,les,fa[N],f[N][22],maxx[N][22],net[N],too[N],ww[N];
int dep[N];
int tot,t,n,m,X,x,y,z;
void clear()
{tot=0;memset(first,0,sizeof(first));for(re int i=1;i<=n;++i)   fa[i]=i;
}
int getfa(int x)
{if(fa[x]!=x)  fa[x]=getfa(fa[x]);return fa[x];
}
void dfs(int x,int faa)
{dep[x]=dep[faa]+1;f[x][0]=faa;for(re int i=1;i<=20;++i)  f[x][i]=f[f[x][i-1]][i-1];for(re int i=1;i<=20;++i) maxx[x][i]=max(maxx[x][i-1],maxx[f[x][i-1]][i-1]);for(re int e=first[x];e;e=net[e]){int v=too[e];if(v==faa)   continue;maxx[v][0]=ww[e];dfs(v,x);}
}
void add(int x,int y,int z)
{net[++tot]=first[x];first[x]=tot;too[tot]=y;ww[tot]=z;
}
int quick(int a,int b)
{int ans=1;while(b){if(b&1)    ans=ans*a%mod;a=a*a%mod;b/=2;}return ans;
}
int query(int a,int b)
{int gu=0;if(dep[a]<dep[b]) swap(a,b);for(int i=20;i>=0;i--){if(dep[f[a][i]]>=dep[b]){gu=max(gu,maxx[a][i]);a=f[a][i];}}if(a==b)   return gu;for(int i=20;i>=0;--i){if(f[a][i]!=f[b][i]){gu=max(gu,max(maxx[a][i],maxx[b][i]));a=f[a][i];b=f[b][i];}}return max(gu,max(maxx[a][0],maxx[b][0]));
}
int cnt,sum,ans;
void solve()
{cnt=sum=ans=equ=les=0;for(re int i=1;i<=m;++i){x=getfa(edge[i].from);y=getfa(edge[i].to);if(x!=y){++cnt;sum+=edge[i].w;fa[x]=y;edge[i].flag=1;add(edge[i].from,edge[i].to,edge[i].w);add(edge[i].to,edge[i].from,edge[i].w);if(cnt==n-1)    break;}}if(sum>X){puts("0");return;}dfs(1,0);int now=sum;for(re int i=1;i<=m;++i){if(!edge[i].flag){now=sum+edge[i].w-query(edge[i].from,edge[i].to);if(now==X)    ++equ;if(now<X)    ++les;}   }if(sum==X)   ans+=(quick(2,m)-2*quick(2,m-n+1-equ)%mod+mod)%mod,ans%=mod;else  ans+=2*(quick(2,m-n+1-les)-quick(2,m-n+1-equ-les)+mod)%mod,ans%=mod;printf("%lld\n",ans);
}
signed main()
{t=read();while(t--){n=read();m=read();X=read();clear();for(re int i=1;i<=m;++i){edge[i].flag=0;edge[i].from=read();edge[i].to=read();edge[i].w=read();}sort(edge+1,edge+1+m);solve();}return 0;
}

T3:耍望节

咕咕咕

191105CSP模拟DAY1相关推荐

  1. GDOI2017第二轮模拟day1 总结

    平民比赛 这场比赛的暴力分非常友好. 但是我并没有拿到全部的暴力分. 1(暴力分\(60/100\)) 暂时我可以拿的暴力分为\(30/100\),直接mst模拟即可. 然而当时打了个辣鸡莫队,结果爆 ...

  2. 省常中模拟 day1

    第一题: 题目大意: 给出N个数的数列,如果相邻的两个数加起来是偶数,那么就可以把这两个数消掉,求最多能消掉多少数. 解题过程: 1.先自己手工模拟了几组数据,发现不管消除的顺序如何,最终剩下的是一定 ...

  3. 黄学长模拟day1 球的序列

    N个编号为1-n的球,每个球都有唯一的编号.这些球被排成两种序列,分别为A.B序列,现在需要重新寻找一个球的序列l,对于这个子序列l中任意的两个球,要求j,k(j<k),都要求满足lj在A中位置 ...

  4. 【JZOJ5073】【GDOI2017第三轮模拟day1】影魔

    Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄. 每一个 ...

  5. 【GDOI2017第三轮模拟day1】影魔(主席树)

    Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄. 每一个 ...

  6. 【GDOI2017第二轮模拟day1】公路建设

    Description 在Byteland一共有n 个城市,编号依次为1 到n,它们之间计划修建m条双向道路,其中修建第i 条道路的费用为ci. Byteasar作为Byteland 公路建设项目的总 ...

  7. 湖南附中模拟day1 金坷垃

    题意描述 "没有金坷垃,怎么种庄稼?" 花花家有一块田,所有庄稼排成了 N 行 M 列.初始时,每棵庄稼都有一个自己的高度 hi;j.花花每次可以使用 1mol 的金克拉使一棵庄稼 ...

  8. NOIP模拟day1 2020.10.28

    不得不说,今天考的4道题感觉质量可以,就是T3数据有点水纯搜索86分可还行 Problem a 如果这道题每个棋子都能是第一个出去的话,那么这道题就简单了,ans便是!n 能骗30多分 ,但是显然受各 ...

  9. jzoj 5062.【GDOI2017第二轮模拟day1】航海舰队 fft

    Description Byteasar 组建了一支舰队!他们现在正在海洋上航行着. 海洋可以抽象成一张n×m 的网格图,其中有些位置是".",表示这一格是海水,可以通过:有些位置 ...

最新文章

  1. 用友二次开发——工资导入
  2. 方法的定义使用,方法重载及方法的递归调用
  3. 处理SAP Netweaver gateway service使用过程中遇到的404 error
  4. 机器学习基础笔记总结
  5. mysql 并发数 任务调度_mysql的计划任务与事件调度实例分析
  6. 不知不觉,到51cto一年了!
  7. Join()--用法
  8. Set集合之HashSet添加的数据是如何保证不重复的
  9. PXE工作流程(PXE启动报错处理)
  10. 湿淀粉 - 搜搜百科
  11. windows系统镜像修复计算机,Win10系统下修复Windows映像方法
  12. KEIL识别不出野火STM32仿真器问题解决
  13. [转]天龙八部的BillingServer
  14. 又一神作,Alibaba“M8级”大老总结微服务与事件驱动架构启蒙手册
  15. 5 种全局 ID 生成方式、优缺点及改进方案
  16. css实现图片自动渐变切换、element-plus 的修改el-table的(边框线为虚线、表头样式)
  17. css3加载中loading代码js特效大全
  18. 数据结构中二叉树的度
  19. 路由器 设置 端口映射
  20. 项目上线后中英文翻译问题解决

热门文章

  1. 土木工程学c语言用啥电脑,学土木类专业需要用笔记本电脑吗?如果需要,什么样的配置合适?...
  2. Java:URL rewrite
  3. Linux tar打包命令
  4. 学习记录439@MySQL json 数据相关操作
  5. Python数据分析之Matplotlib的常用操作总结
  6. python中json用法loads和dumps区别_pythonjsondumps与loads
  7. python帮助和文档、希腊字母对照表
  8. 软件测试(五)ios测试1-屏蔽 iOS 系统升级提示的方法
  9. Win11玩绝地求生(PUBG)崩溃怎么办?Win11玩绝地求生崩溃解决方法
  10. 玩吃鸡提示显卡内存不足闪退的解决办法