校内模拟赛划水报告(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;
}

  

posted @ 2019-09-15 13:29  ninelifecat  阅读(162)  评论(0编辑  收藏  举报