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;
}
原文:https://www.cnblogs.com/ninelifecat/p/11521965.html