zoukankan      html  css  js  c++  java
  • Codeforces Round #636 (Div. 3) 题解

    想来划划水,结果被打爆了/kk

    A

    ((2^k-1)x=n),枚举(k)即可。

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    #include<bitset>
    #include<math.h>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    typedef long long ll;
    typedef long double db;
    typedef vector<int> vi;
    typedef pair<int,int> pii;
    const int N=100000;
    const db pi=acos(-1.0);
    #define lowbit(x) (x)&(-x)
    #define sqr(x) (x)*(x)
    #define rep(i,a,b) for (register int i=a;i<=b;i++)
    #define per(i,a,b) for (register int i=a;i>=b;i--)
    #define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
    #define fir first
    #define sec second
    #define mkp make_pair
    #define pb push_back
    #define maxd 998244353
    #define eps 1e-8
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
        while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
        return x*f;
    }
    
    namespace My_Math{
    	#define N 100000
    
    	int fac[N+100],invfac[N+100];
    
    	int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
    	int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
    	int mul(int x,int y) {return 1ll*x*y%maxd;}
    	ll qpow(ll x,int y)
    	{
    		ll ans=1;
    		while (y)
    		{
    			if (y&1) ans=mul(ans,x);
    			x=mul(x,x);y>>=1;
    		}
    		return ans;
    	}
    	int getinv(int x) {return qpow(x,maxd-2);}
    
    	int C(int n,int m)
    	{
    		if ((n<m) || (n<0) || (m<0)) return 0;
    		return mul(mul(fac[n],invfac[m]),invfac[n-m]);
    	}
    
    	void math_init()
    	{
    		fac[0]=invfac[0]=1;
    		rep(i,1,N) fac[i]=mul(fac[i-1],i);
    		invfac[N]=getinv(fac[N]);
    		per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
    	}
    	#undef N
    }
    using namespace My_Math;
    
    int main()
    {
    	int T=read();
    	while (T--)
    	{
    		ll n;scanf("%lld",&n);
    		ll k=3;
    		while (n>=k)
    		{
    			if (n%k==0)
    			{
    				printf("%lld
    ",n/k);
    				break;
    			}
    			k=k*2+1;
    		}
    	}
    	return 0;
    }
    

    B

    (frac{n}{2})为奇数时显然无解(因为右半边的和为奇数)

    否则可进行如(2,4,cdots,n,1,3,cdots,2n-3,x)的构造,其中(x)根据前面的数做差得到。

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    #include<bitset>
    #include<math.h>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    typedef long long ll;
    typedef long double db;
    typedef vector<int> vi;
    typedef pair<int,int> pii;
    const int N=100000;
    const db pi=acos(-1.0);
    #define lowbit(x) (x)&(-x)
    #define sqr(x) (x)*(x)
    #define rep(i,a,b) for (register int i=a;i<=b;i++)
    #define per(i,a,b) for (register int i=a;i>=b;i--)
    #define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
    #define fir first
    #define sec second
    #define mkp make_pair
    #define pb push_back
    #define maxd 998244353
    #define eps 1e-8
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
        while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
        return x*f;
    }
    
    namespace My_Math{
    	#define N 100000
    
    	int fac[N+100],invfac[N+100];
    
    	int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
    	int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
    	int mul(int x,int y) {return 1ll*x*y%maxd;}
    	ll qpow(ll x,int y)
    	{
    		ll ans=1;
    		while (y)
    		{
    			if (y&1) ans=mul(ans,x);
    			x=mul(x,x);y>>=1;
    		}
    		return ans;
    	}
    	int getinv(int x) {return qpow(x,maxd-2);}
    
    	int C(int n,int m)
    	{
    		if ((n<m) || (n<0) || (m<0)) return 0;
    		return mul(mul(fac[n],invfac[m]),invfac[n-m]);
    	}
    
    	void math_init()
    	{
    		fac[0]=invfac[0]=1;
    		rep(i,1,N) fac[i]=mul(fac[i-1],i);
    		invfac[N]=getinv(fac[N]);
    		per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
    	}
    	#undef N
    }
    using namespace My_Math;
    
    int main()
    {
    	int T=read();
    	while (T--)
    	{
    		int n=read();
    		if (n%4) {puts("NO");continue;}
    		else
    		{
    			puts("YES");
    			ll sum=0;
    			rep(i,1,n>>1) 
    			{
    				printf("%d ",(i<<1));
    				sum+=(i<<1);
    			}
    			rep(i,1,(n>>1)-1)
    			{
    				printf("%d ",i*2-1);
    				sum-=(i*2-1);
    			}
    			printf("%d
    ",sum);
    		}
    	}
    	return 0;
    }
    

    C

    在每一个同符号的极长连续段中取最大的数即为答案。

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    #include<bitset>
    #include<math.h>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    typedef long long ll;
    typedef long double db;
    typedef vector<int> vi;
    typedef pair<int,int> pii;
    const int N=100000;
    const db pi=acos(-1.0);
    #define lowbit(x) (x)&(-x)
    #define sqr(x) (x)*(x)
    #define rep(i,a,b) for (register int i=a;i<=b;i++)
    #define per(i,a,b) for (register int i=a;i>=b;i--)
    #define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
    #define fir first
    #define sec second
    #define mkp make_pair
    #define pb push_back
    #define maxd 998244353
    #define eps 1e-8
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
        while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
        return x*f;
    }
    
    namespace My_Math{
    	#define N 100000
    
    	int fac[N+100],invfac[N+100];
    
    	int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
    	int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
    	int mul(int x,int y) {return 1ll*x*y%maxd;}
    	ll qpow(ll x,int y)
    	{
    		ll ans=1;
    		while (y)
    		{
    			if (y&1) ans=mul(ans,x);
    			x=mul(x,x);y>>=1;
    		}
    		return ans;
    	}
    	int getinv(int x) {return qpow(x,maxd-2);}
    
    	int C(int n,int m)
    	{
    		if ((n<m) || (n<0) || (m<0)) return 0;
    		return mul(mul(fac[n],invfac[m]),invfac[n-m]);
    	}
    
    	void math_init()
    	{
    		fac[0]=invfac[0]=1;
    		rep(i,1,N) fac[i]=mul(fac[i-1],i);
    		invfac[N]=getinv(fac[N]);
    		per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
    	}
    	#undef N
    }
    using namespace My_Math;
    
    int n,a[200100];
    
    int calc(int x)
    {
    	if (x>0) return 1;else return -1;
    }
    
    int main()
    {
    	int T=read();
    	while (T--)
    	{
    		n=read();
    		rep(i,1,n) a[i]=read();
    		ll ans=0,sum=0;
    		int pos=1,mx=a[1];
    		rep(i,2,n)
    		{
    			if (calc(a[i])==calc(a[pos]))
    			{
    				mx=max(mx,a[i]);
    			}
    			else
    			{
    				ans+=mx;pos=i;mx=a[i];
    			}
    		}
    		ans+=mx;
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    

    D

    枚举(x),求出对每个(x)的修改次数。

    注意到对一对数((a,b)(a<b)).要是想只修改一个数的话必有(xin[a+1,b+k]),否则就要修改两个数。用一个set维护当前的(x)在哪些数对的区间中。

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    #include<bitset>
    #include<math.h>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    typedef long long ll;
    typedef long double db;
    typedef vector<int> vi;
    typedef pair<int,int> pii;
    const int N=1000000+100;
    const db pi=acos(-1.0);
    #define lowbit(x) (x)&(-x)
    #define sqr(x) (x)*(x)
    #define rep(i,a,b) for (register int i=a;i<=b;i++)
    #define per(i,a,b) for (register int i=a;i>=b;i--)
    #define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
    #define fir first
    #define sec second
    #define mkp make_pair
    #define pb push_back
    #define maxd 998244353
    #define eps 1e-8
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
        while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
        return x*f;
    }
    
    namespace My_Math{
    	#define N 100000
    
    	int fac[N+100],invfac[N+100];
    
    	int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
    	int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
    	int mul(int x,int y) {return 1ll*x*y%maxd;}
    	ll qpow(ll x,int y)
    	{
    		ll ans=1;
    		while (y)
    		{
    			if (y&1) ans=mul(ans,x);
    			x=mul(x,x);y>>=1;
    		}
    		return ans;
    	}
    	int getinv(int x) {return qpow(x,maxd-2);}
    
    	int C(int n,int m)
    	{
    		if ((n<m) || (n<0) || (m<0)) return 0;
    		return mul(mul(fac[n],invfac[m]),invfac[n-m]);
    	}
    
    	void math_init()
    	{
    		fac[0]=invfac[0]=1;
    		rep(i,1,N) fac[i]=mul(fac[i-1],i);
    		invfac[N]=getinv(fac[N]);
    		per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
    	}
    	#undef N
    }
    using namespace My_Math;
    
    int n,k,a[N],sum[N],mn[N];
    struct node{int id,l,r;}seg[N];
    bool operator <(node p,node q) {return p.r<q.r;}
    bool cmp(node p,node q) {return p.l<q.l;}
    multiset<node> s;
    multiset<node>::iterator it;
    vi ask;
    
    int main()
    {
    	int T=read();
    	while (T--)
    	{
    		n=read();k=read();
    		rep(i,1,n) a[i]=read();
    		rep(i,1,n>>1)
    		{
    			sum[a[i]+a[n-i+1]]++;
    			int mn=min(a[i],a[n-i+1]),mx=max(a[i],a[n-i+1]);
    			seg[i]=(node){i,mn+1,mx+k};
    		}
    		sort(seg+1,seg+1+(n>>1),cmp);
    		int ans=n;int pos=1;
    		rep(x,2,k*2)
    		{
    			while (!s.empty())
    			{
    				it=s.begin();node tmp=*it;
    				if (x>tmp.r) s.erase(it);else break;
    			}
    			while ((pos<=(n>>1)) && (seg[pos].l==x))
    			{
    				s.insert(seg[pos]);pos++;
    			}
    			int siz=s.size();
    			int now=siz-sum[x]+(n/2-siz)*2;
    			ans=min(ans,now);
    		}
    		s.clear();
    		printf("%d
    ",ans);
    		rep(i,1,k*2) sum[i]=0;
    	}
    	return 0;
    }
    

    E

    (a o b o c)的路径可以看成(a o b)(c o b)的两条,注意到这两条路径在相交后就彼此贴贴重合,于是可以枚举这个相交点,之后再这个点到(a,b,c)的路径上贪心的放置权值即可,注意由于到(b)的路径要走两次所以要优先放且其贡献需( imes 2)。预处理需要分别以(a,b,c)为源跑三遍最短路。

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    #include<bitset>
    #include<math.h>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    typedef long long ll;
    typedef long double db;
    typedef vector<int> vi;
    typedef pair<int,int> pii;
    const int N=200000+100;
    const db pi=acos(-1.0);
    #define lowbit(x) (x)&(-x)
    #define sqr(x) (x)*(x)
    #define rep(i,a,b) for (register int i=a;i<=b;i++)
    #define per(i,a,b) for (register int i=a;i>=b;i--)
    #define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
    #define fir first
    #define sec second
    #define mkp make_pair
    #define pb push_back
    #define maxd 998244353
    #define eps 1e-8
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
        while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
        return x*f;
    }
    
    namespace My_Math{
    	#define N 100000
    
    	int fac[N+100],invfac[N+100];
    
    	int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
    	int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
    	int mul(int x,int y) {return 1ll*x*y%maxd;}
    	ll qpow(ll x,int y)
    	{
    		ll ans=1;
    		while (y)
    		{
    			if (y&1) ans=mul(ans,x);
    			x=mul(x,x);y>>=1;
    		}
    		return ans;
    	}
    	int getinv(int x) {return qpow(x,maxd-2);}
    
    	int C(int n,int m)
    	{
    		if ((n<m) || (n<0) || (m<0)) return 0;
    		return mul(mul(fac[n],invfac[m]),invfac[n-m]);
    	}
    
    	void math_init()
    	{
    		fac[0]=invfac[0]=1;
    		rep(i,1,N) fac[i]=mul(fac[i-1],i);
    		invfac[N]=getinv(fac[N]);
    		per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
    	}
    	#undef N
    }
    using namespace My_Math;
    
    struct node{int to,nxt;}sq[N<<1];
    int all=0,head[N];
    int n,m,a,b,c,dis[3][N];
    bool vis[N];
    ll w[N];
    struct hnode{int u,dis;};
    bool operator <(hnode p,hnode q) {return p.dis>q.dis;}
    priority_queue<hnode> q;
    
    void addedge(int u,int v)
    {
    	all++;sq[all].to=v;sq[all].nxt=head[u];head[u]=all;
    }
    
    void dij(int st,int *dis)
    {
    	rep(i,1,n) dis[i]=maxd,vis[i]=0;
    	q.push((hnode){st,0});dis[st]=0;
    	while (!q.empty())
    	{
    		int u=q.top().u;q.pop();
    		if (vis[u]) continue;vis[u]=1;
    		go(u,i)
    		{
    			if (dis[v]>dis[u]+1)
    			{
    				dis[v]=dis[u]+1;
    				if (!vis[v]) q.push((hnode){v,dis[v]});
    			}
    		}
    	}
    }
    
    ll calc(int l,int r) 
    {
    	if (r>m) return 1e18;
    	else return w[r]-w[l-1];
    }
    
    int main()
    {
    	int T=read();
    	while (T--)
    	{
    		n=read();m=read();a=read();b=read();c=read();
    		rep(i,1,m) w[i]=read();
    		sort(w+1,w+1+m);
    		rep(i,1,m) w[i]+=w[i-1];
    		rep(i,1,m)
    		{
    			int u=read(),v=read();
    			addedge(u,v);addedge(v,u);
    		}
    		dij(b,dis[0]);dij(a,dis[1]);dij(c,dis[2]);
    		ll ans=1e18;
    		rep(i,1,n)
    		{
    			int x=dis[0][i],y=dis[1][i],z=dis[2][i];
    			ll now=calc(1,x)*2+calc(x+1,x+y)+calc(x+y+1,x+y+z);
    			ans=min(ans,now);
    		}
    		printf("%lld
    ",ans);
    		rep(i,1,n) head[i]=0;all=0;
    	}
    	return 0;
    }
    

    写个dij都调了一万年我菜爆了

    F

    差不多想到了但没时间写了,我真是菜啊

    注意到当(r=2)时其对应的(l)必为(1),也就是这个区间的长度为(2),于是我们可以枚举所有长度为(2)的区间同时确定(p_1,p_2).

    如果我们删去所有给定区间中的(p_1,p_2), 那么对于(r=3)的区间肯定只剩下了(p_3),而对(r>3)的区间至少还有两个元素,依次递推下去(在不出现找不到或有多于1个的长度为(1)的情况时)就能确定整个排列。而出现上述非法情况时就说明当前枚举的(p_1,p_2)是错误的,需要重新枚举。

    然而这样还会有一个问题:(p_1)(p_2)的相对位置不确定,笔者的处理方法是对题目中所给的区间再重新check一遍。由于每个区间在排列中至多出现一次,所以可以直接暴力check.

    #include<iostream>
    #include<string.h>
    #include<string>
    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    #include<bitset>
    #include<math.h>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    typedef long long ll;
    typedef long double db;
    typedef vector<int> vi;
    typedef pair<int,int> pii;
    const int N=200+50;
    const db pi=acos(-1.0);
    #define lowbit(x) (x)&(-x)
    #define sqr(x) (x)*(x)
    #define rep(i,a,b) for (register int i=a;i<=b;i++)
    #define per(i,a,b) for (register int i=a;i>=b;i--)
    #define go(u,i) for (register int i=head[u],v=sq[i].to;i;i=sq[i].nxt,v=sq[i].to)
    #define fir first
    #define sec second
    #define mkp make_pair
    #define pb push_back
    #define maxd 998244353
    #define eps 1e-8
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
        while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
        return x*f;
    }
    
    namespace My_Math{
    	#define N 100000
    
    	int fac[N+100],invfac[N+100];
    
    	int add(int x,int y) {return x+y>=maxd?x+y-maxd:x+y;}
    	int dec(int x,int y) {return x<y?x-y+maxd:x-y;}
    	int mul(int x,int y) {return 1ll*x*y%maxd;}
    	ll qpow(ll x,int y)
    	{
    		ll ans=1;
    		while (y)
    		{
    			if (y&1) ans=mul(ans,x);
    			x=mul(x,x);y>>=1;
    		}
    		return ans;
    	}
    	int getinv(int x) {return qpow(x,maxd-2);}
    
    	int C(int n,int m)
    	{
    		if ((n<m) || (n<0) || (m<0)) return 0;
    		return mul(mul(fac[n],invfac[m]),invfac[n-m]);
    	}
    
    	void math_init()
    	{
    		fac[0]=invfac[0]=1;
    		rep(i,1,N) fac[i]=mul(fac[i-1],i);
    		invfac[N]=getinv(fac[N]);
    		per(i,N-1,1) invfac[i]=mul(invfac[i+1],i+1);
    	}
    	#undef N
    }
    using namespace My_Math;
    
    int n,len[N],siz[N],ans[N];
    bool used[N];
    vi a[N];
    
    void out()
    {
    	rep(i,1,n) printf("%d ",ans[i]);puts("");
    }
    
    void clr()
    {
    	rep(i,1,n-1) a[i].clear();
    }
    
    bool chk()
    {
    	vi tmp;
    	rep(i,1,n) used[i]=0;
    	rep(i,1,n-1)
    	{
    		int ok=0;
    		rep(j,1,n-siz[i]+1)
    		{
    			tmp.clear();
    			rep(k,1,siz[i]) tmp.pb(ans[j+k-1]);
    			sort(tmp.begin(),tmp.end());
    			if (tmp==a[i])
    			{
    				int r=j+siz[i]-1;
    				if (used[r]) return 0;
    				used[r]=1;ok=1;break;
    			}
    		}
    		if (!ok) return 0; 
    	}
    	return 1;
    }
    
    bool solve(int id)
    {
    	rep(i,1,n-1)
    	{
    		len[i]=siz[i];
    	}
    	int x=a[id][0],y=a[id][1];
    	rep(i,1,n) used[i]=0;
    	used[x]=used[y]=1;
    	rep(i,1,n-1)
    	{
    		rep(j,0,siz[i]-1)
    			if ((a[i][j]==x) || (a[i][j]==y)) len[i]--;
    	}
    	rep(x,3,n)
    	{
    		int pos=0;
    		rep(i,1,n-1)
    		{
    			if (len[i]==1)
    			{
    				if (pos) return 0;
    				pos=i;
    			}
    		}
    		if (!pos) return 0;
    		int val;
    		rep(i,0,siz[pos]-1)
    			if (!used[a[pos][i]]) val=a[pos][i];
    		if (used[val]) return 0;
    		ans[x]=val;used[val]=1;
    		rep(i,1,n-1)
    		{
    			rep(j,0,siz[i]-1)
    				if (a[i][j]==val) len[i]--;
    		}
    	}
    	if (chk()) return 1;else return 0;
    }
    
    int main()
    {
    	int T=read();
    	while (T--)
    	{
    		n=read();
    		rep(i,1,n-1)
    		{
    			siz[i]=read();
    			rep(j,1,siz[i])
    			{
    				int x=read();
    				a[i].pb(x);
    			}
    		}
    		rep(i,1,n-1)
    		{
    			if (siz[i]!=2) continue;
    			ans[1]=a[i][0];ans[2]=a[i][1];
    			if (solve(i)) {out();break;}
    			ans[1]=a[i][1];ans[2]=a[i][0];
    			if (solve(i)) {out();break;}
    		}
    		clr();
    	}
    	return 0;
    }
    
  • 相关阅读:
    PowerDesigner小技巧(整理中)
    将日志(Microsoft.Extensions.Logging)添加到.NET Core控制台应用程序
    VMware Workstation Pro 15.5.0 官方版本及激活密钥
    Git 设置和取消代理(SOCKS5代理)
    笔记
    哈希表(Hash Table)与哈希算法
    Elasticsearch分词
    微服务理论
    Elasticsearch与Mysql数据同步
    go语言常用命令
  • 原文地址:https://www.cnblogs.com/encodetalker/p/12757960.html
Copyright © 2011-2022 走看看