5.27 ZJ W11 T4
#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
using namespace std;
struct Node{
int pos,val;
bool operator < (const Node &A) const{
if (val!=A.val) return val>A.val;
else return pos<A.pos;
//错误:
//return val>A.val;
}
Node(){}
Node(int V,int P){
val=V; pos=P;
}
};
multiset <Node> S;
int n,M,l[300030],r[300030],A[300030],ans;
int main(){
int i;
scanf("%d %d",&n,&M);
if (2*M>n){
cout<<"Error!"; return 0;
}
for (i=1;i<=n;i++){
scanf("%d",&A[i]);
S.insert(Node(A[i],i));
l[i]=i-1; r[i]=i+1;
}
l[1]=n; r[n]=1;
while (M--){
Node cur=*S.begin();
ans+=cur.val; int pos=cur.pos;
A[pos]=A[l[pos]]+A[r[pos]]-A[pos];
S.erase(cur);
S.erase(Node(A[l[pos]],l[pos]));
S.erase(Node(A[r[pos]],r[pos]));
int newl=l[l[pos]],newr=r[r[pos]];
r[newl]=pos; l[newr]=pos; l[pos]=newl; r[pos]=newr;
S.insert(Node(A[pos],pos));
}
cout<<ans;
}
set的元素是结构体,里面有两个int,然而发现insert的时候只要有一个值一样就会默认是一样的。因为自定义小于号只比较了第一个值,没比较第二个所以默认一样,以后注意用set一定要把结构体所有值全比较
然后我灵机一动用了multiset,小于号还是只比较了一个,insert可以insert但是erase删除不掉元素,find也re
(如果multiset元素是int,插入了多个2,erase一下会把所有的2全删,可以erase(S.find(2))
5.27 ZR W11 T5
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N (20020)
#define INF (2000000010)
using namespace std;
struct orz{
int x,y,val;
void Read(){
scanf("%d %d %d",&x,&y,&val);
}
bool operator < (const orz &A) const{
return val<A.val;
}
}Gra[N];
struct edge{
int next,to,val;
void Add(int Next,int To,int V){
next=Next; to=To; val=V;
}
}q[N];
int n,m,fa[N],m1,dep[N],f[N][30],A[N],T[N][30],h[N];
int fin(int x){
if (x==fa[x]) return x;
fa[x]=fin(fa[x]);
return fa[x];
}
void addedge(int x,int y,int val){
q[++m1].Add(h[x],y,val); h[x]=m1;
q[++m1].Add(h[y],x,val); h[y]=m1;
}
void Dfs(int x){
for (int i=h[x];i;i=q[i].next){
int y=q[i].to;
if (y==fa[x]) continue;
fa[y]=x; dep[y]=dep[x]+1; A[y]=q[i].val;
Dfs(y);
}
}
int main(){
cin>>n>>m;
int i,j;
for (i=1;i<=m;i++) Gra[i].Read();
sort(Gra+1,Gra+m+1);
for (i=1;i<=n;i++) fa[i]=i;
for (i=1;i<=m;i++){
if (fin(Gra[i].x)==fin(Gra[i].y)) continue;
fa[fin(Gra[i].x)]=fin(Gra[i].y);
addedge(Gra[i].x,Gra[i].y,Gra[i].val);
}
memset(fa,0,sizeof(fa));
Dfs(1);
for (i=1;i<=n;i++) f[i][0]=A[i],T[i][0]=fa[i];
for (j=1;j<=15;j++)
for (i=1;i<=n;i++){
T[i][j]=T[T[i][j-1]][j-1];
f[i][j]=max(f[i][j-1],f[T[i][j-1]][j-1]);
}
int x,y,Q; cin>>Q;
while (Q--){
scanf("%d %d",&x,&y);
if (dep[x]<dep[y]) swap(x,y);
if (x==y){
cout<<0<<endl; continue;
}
int ans=0;
for (i=15;i>=0;i--){
if (dep[T[x][i]]>=dep[y]){//写成<=了
ans=max(ans,f[x][i]);
x=T[x][i];
}
}
if (x==y){
printf("%d\n",ans);
continue;
}
for (i=15;i>=0;i--){
if (T[x][i]!=T[y][i]) {
ans=max(ans,f[x][i]);
ans=max(ans,f[y][i]);
x=T[x][i]; y=T[y][i];
}
}
ans=max(ans,f[x][0]); ans=max(ans,f[y][0]);//这两句漏了
printf("%d\n",ans);
}
}
倍增写的不熟
1.把靠下的点跳到和靠上的点一样高度时dep>=写成<=
2.忘了两点都跳成lca子节点时再向上一步
之前
没想到,一道AC自动机板子题,竟然出了这么zz的错误。strlen函数计算多次,t到飞起
更久之前(4.1)
day1,三个板子题,t3数据出锅暂且不表,t1虽然对规律似懂非懂,但是还是靠打表找出了规律。
然而也不知道脑子是不是抽了,内存充裕到要死手欠把后缀数组求Sa的桶从MAXN改成了200(当时我好像想的是ASCII码最多到122?exm?后来一想排名会越来越大最后也会到MAXN啊,还调了一节多晚自习无解了)
day2就更加的无解了,t1KMP没看出来怎么转化也就还则罢了,送的十分也没拿上?还zz地调了一节课,发现原来是自己数组开大了。本来就是冲着1000的数据去的,非要开一百万以为能多过一个点?%%%褚队心思缜密,对着褚队的程序发现的。memset了3000次啊,把数组从一百万改成2000瞬间1.02秒到0ms,也是很稳健能自己用开大数组稳稳地卡掉自己
day1数组开小从ac到爆零,day2数组开大活活memset到t,剧本都不敢这么写好吗
愚人节两轮没犯什么技术性错误,但是这种小错误以后比赛更要注意