校内模拟赛划水报告(9.9,9.11)
D1T1:
由于两个数在加小于min(lowbit(x),lowbit(y))的数对他们的奇偶性不影响
所以直接暴力跳,lowbit到底,最后是nlogn^3???
#include<cstdio> #include<algorithm> #define int long long using namespace std; int a[100010]; int lowbit(int x) { return x&(-x); } int check(int x) { int ans=0; while(x) { x-=lowbit(x); ans++; } return ans; } bool cmp(int x,int y) { while((check(x)&1)==(check(y)&1)) { int ans=min(lowbit(x),lowbit(y)); x+=ans; y+=ans; } if(check(x)&1) return 0; else return 1; } signed main() { int n; scanf("%lld",&n); for(int i=1;i<=n;i++) scanf("%lld",&a[i]); sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++) printf("%lld ",a[i]); return 0; }
D1T2:直接二分天数然后暴力check即可
#include<cstdio> #include<algorithm> #define int long long using namespace std; int a[100010],b[100010],c[100010],n; int check(int x) { int ans=0; for(int i=1;i<=n;i++) { if(a[i]-b[i]*x>0) ans+=max(0ll,(a[i]-b[i]*x-1)/c[i]+1); } if(ans<=x) return 1; else return 0; } signed main() { scanf("%lld",&n); int mmin=99999999999ll; int mmax=-1; for(int i=1;i<=n;i++) { scanf("%lld%lld%lld",&a[i],&b[i],&c[i]); int cnt=(a[i]-1)/b[i]+1; mmin=min(mmin,cnt); mmax=max(mmax,cnt); } int l=0,r=mmax; while(l<r) { int mid=(l+r)/2; if(check(mid)) { r=mid; } else { l=mid+1; } } printf("%lld",l); return 0; }
D1T3:枚举第k条边是什么然后对每一条边的边权=max(e[i].v-V,0)然后再跑单源最短路 最后答案+V*k即可
#include<cstdio> #include<cstring> #include<queue> #define int long long using namespace std; int n,m; int k,s,t; struct edge { int v,last,w; }e[1000010],e2[1000010]; int in[1000010],cnt=0; void addedge(int x,int y,int z) { e2[++cnt].v=y; e2[cnt].w=z; e2[cnt].last=in[x]; in[x]=cnt; } const int inf=99999999999ll; struct node { int dist,pos; bool operator <(const node &x)const { return x.dist<dist; } }; priority_queue<node> q; int dis[1000010]; bool vis[1000010]; int dijkstra() { int i,x,y; node tmp; for(int i=1;i<=n;i++) { vis[i]=0; dis[i]=inf; } dis[s]=0; q.push((node){0,s}); while(!q.empty()) { tmp=q.top();q.pop(); x=tmp.pos; if(vis[x]!=0)continue; vis[x]=1; for(i=in[x];i;i=e[i].last) { y=e[i].v; if(dis[y]>dis[x]+e[i].w) { dis[y]=dis[x]+e[i].w; if(vis[y]==0) q.push((node){dis[y],y}); } } } return dis[t]; } signed main() { int x,y,v; int ans=inf; scanf("%lld%lld%lld%lld%lld",&n,&m,&k,&s,&t); for(int i=1;i<=m;i++) { scanf("%lld%lld%lld",&x,&y,&v); addedge(x,y,v); } memcpy(e,e2,sizeof(e2)); for(int i=1;i<=m;i++) { for(int j=1;j<=m;j++) e[j].w=max(e2[j].w-e2[i].w,0ll); ans=min(ans,dijkstra()+e2[i].w*k); } printf("%lld",ans); return 0; }
D2T1:有一条线交换两个数即可,最后考虑如果交换成顺序就说明这条横线必须取,求出为逆序对即可
#include<cstdio> #define ing long long using namespace std; int n,m; int a[1000010]; int b[1000010]; int lowbit(int k) { return k&(-k); } void add(int x) { while(x<=n) { b[x]+=1; x+=lowbit(x); } } int count(int x) { int sum=0; while(x!=0) { sum+=b[x]; x-=lowbit(x); } return sum; } signed main() { //freopen("permutation.in","r",stdin); //freopen("permutation.out","w",stdout); int x; scanf("%lld%lld",&n,&m); for(int i=1;i<=n;i++) a[i]=i; for(int i=1;i<=m;i++) { scanf("%lld",&x); int temp=a[x]; a[x]=a[x+1]; a[x+1]=temp; } for(int i=1;i<=n;i++) printf("%lld ",a[i]); printf("\n"); int cnt=0; for(int i=1;i<=n;i++) { add(a[i]); cnt+=i-count(a[i]); } printf("%lld",cnt); return 0; }
D2T2:
先跑最小生成树,如果有边答案就是这个最小生成树,反之加边,并用这个遍替换掉最大的遍,用LCA倍增求解即可
#include<cstdio> #include<algorithm> #define int long long using namespace std; int n,m,f[400050][30],cnt,head[400050],fa[400050],dep[400050],vis[400050]; int ans,o[400050],lg[400050]; int mmax[400050][30]; struct node { int f,t,v,id; }a[400050<<1]; struct Node { int v,val,nex; }e[400050<<1]; int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); } inline void add(int u,int v,int w) { cnt++; e[cnt].v=v; e[cnt].val=w; e[cnt].nex=head[u]; head[u]=cnt; } void dfs(int cur,int faa) { int i; dep[cur]=dep[faa]+1; f[cur][0]=faa; for(i=1;(1<<i)<=dep[cur];i++) f[cur][i]=f[f[cur][i-1]][i-1],mmax[cur][i]=max(mmax[cur][i-1],mmax[f[cur][i-1]][i-1]);; for(i=head[cur];i;i=e[i].nex) { int p=e[i].v; if(p==faa) continue; if(dep[p]) continue; f[p][0]=cur; mmax[p][0]=e[i].val; dfs(p,cur); } } int lca(int x,int y) { int i,temp; int ans=0; if(dep[x]<dep[y]) { temp=x;x=y;y=temp; } for(int i=lg[dep[x]];i>=0;i--) if(dep[f[x][i]]>=dep[y]) { ans=max(ans,mmax[x][i]); x=f[x][i]; } if(x==y)return ans; for(i=lg[dep[x]];i>=0;i--) { if(f[x][i]!=f[y][i]) { ans=max(ans,max(mmax[x][i],mmax[y][i])); x=f[x][i]; y=f[y][i]; } } ans=max(ans,max(mmax[x][0],mmax[y][0])); return ans; } bool cmp(node x,node y) { return x.v<y.v; } bool cmp1(node x,node y) { return x.id<y.id; } signed main() { scanf("%lld%lld",&n,&m); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) { scanf("%lld%lld%lld",&a[i].f,&a[i].t,&a[i].v); a[i].id=i; } sort(a+1,a+1+m,cmp); int tot=0; for(int i=1;i<=m;i++) { int xx=find(a[i].f); int yy=find(a[i].t); if(xx==yy) continue; ans+=(int)a[i].v; fa[xx]=yy;tot+=1; vis[a[i].id]=1; add(a[i].f,a[i].t,a[i].v); add(a[i].t,a[i].f,a[i].v); if(tot>=n-1)break; } for(int i=1;i<=n;i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i); dfs(1,0); sort(a+1,a+1+m,cmp1); /* for(int i=1;i<=m;i++) printf("%lld\n",lca(a[i].f,a[i].t)); */ for(int i=1;i<=m;i++) { if(vis[a[i].id]) printf("%lld\n",ans); else printf("%lld\n",(ans+a[i].v-lca(a[i].f,a[i].t))); } return 0; }
D2T3:考虑最后满足偶数,所以一直01异或满足最后是0即可,我们折半搜索,最后合并时查出值相等的最大值(因为用的map最后用了各种卡常才过了最后一个点。。。。)
#pragma GCC optimize("O3") #pragma GCC optimize("Ofast,no-stack-protector") #pragma GCC optimize("Ofast") #pragma GCC target("sse3","sse2","sse") #pragma GCC target("avx","sse4","sse4.1","sse4.2","ssse3") #pragma GCC target("f16c") #pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector") #pragma GCC diagnostic error "-fwhole-program" #pragma GCC diagnostic error "-fcse-skip-blocks" #pragma GCC diagnostic error "-funsafe-loop-optimizations" #pragma GCC diagnostic error "-std=c++14" #include<cstdio> #include<algorithm> #include<cstring> #include<unordered_map> #include<cctype> using namespace std; int n,a[1010],ans2,stk[1000010],tail; long long ans1; unordered_map<long long,int> m1,m2,vis,q1,q2; char s[1010]; int read() { int f=1,x=0; char ch=' '; for(;!isdigit(ch);ch=getchar())if(ch=='-')f*=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return f*x; } int main() { n=read(); for(int i=1;i<=n;i++) { scanf("%s",s); int len=strlen(s); for(int j=0;j<len;++j) a[i]=a[i]^(1<<(s[j]-'a')); } for(int i=0;i<(1<<(n/2));i++) { int res1=0,res2=0,num=0; for(int j=1,u=i;j<=n/2;++j,u>>=1) if(u&1) { res1=res1^a[j]; res2=res2^a[j+n/2]; num++; } m1[res1]++; q1[res1]=max(num,q1[res1]); m2[res2]++; q2[res2]=max(num,q2[res2]); if(!vis[res1]) { vis[res1]=1; stk[++tail]=res1; } } for(int i=1;i<=tail;i++) { int res=stk[i]; ans1+=1ll*m1[res]*m2[res]; vis[res]=1; if((m1[res]==0||m2[res]==0)&&res!=0) continue; ans2=max(ans2,q1[res]+q2[res]); } printf("%lld %d",ans1-1,ans2); return 0; }