zoukankan      html  css  js  c++  java
  • Codechef August Challenge 2019 Division 2

    Preface

    老年菜鸡终于开始打CC了,由于他太弱了所以只能打Div2

    因为台风的原因challenge并没有写,所以水了个Rank7


    A Football

    SB模拟题不解释

    #include<cstdio>
    #include<iostream>
    #define RI register int
    using namespace std;
    const int N=155;
    int t,n,a[N],b[N],ans;
    int main()
    {
    	for (scanf("%d",&t);t;--t)
    	{
    		RI i; for (ans=0,scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&a[i]);
    		for (i=1;i<=n;++i) scanf("%d",&b[i]),ans=max(ans,20*a[i]-10*b[i]);
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

    B Distribute Apples

    题意杀,简单分析之后发现如果(k^2|n)就是NO,否则就是YES

    #include<cstdio>
    #include<iostream>
    #define RI register int
    using namespace std;
    int t; long long n,k;
    int main()
    {
    	for (scanf("%d",&t);t;--t)
    	{
    		scanf("%lld%lld",&n,&k);
    		if (n/k<k) { puts("YES"); continue; }
    		puts(n%(k*k)?"YES":"NO");
    	}
    	return 0;
    }
    

    C Dilemma

    首先不考虑有(0)的情况,我们发现长度为奇数的(1)就是合法的

    考虑在两段(1)中间插入一段(0),手玩一下发现加入多少都是没有影响的

    因此我们按照连续的(1)的奇偶性个数讨论,如果奇数的连续的(1)有奇数段就是合法的,否则不合法

    #include<cstdio>
    #include<cstring>
    #define RI register int
    using namespace std;
    const int N=100005;
    int t,n; char s[N];
    int main()
    {
    	for (scanf("%d",&t);t;--t)
    	{
    		scanf("%s",s+1); n=strlen(s+1); int num=0,len=0;
    		for (RI i=1;i<=n;++i) if (s[i]=='1')
    		{
    			if (s[i-1]=='1') ++len; else num+=len&1,len=1;
    		}
    		num+=len&1; puts(num&1?"WIN":"LOSE");
    	}
    	return 0;
    }
    

    D Zombie and the Caves

    刚开始看错题了,以为要重排这个序列来构造方案

    没想到是直接模拟判断是否可行即可,区间加单点求值差分一下即可

    #include<cstdio>
    #include<cctype>
    #include<iostream>
    #include<algorithm>
    #define RI register int
    #define CI const int&
    #define Tp template <typename T>
    using namespace std;
    const int N=100005;
    int t,n,x,h[N],dlt[N];
    class FileInputOutput
    {
    	private:
    		static const int S=1<<21;
    		#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
    		char Fin[S],*A,*B;
    	public:
    		Tp inline void read(T& x)
    		{
    			x=0; char ch; while (!isdigit(ch=tc()));
    			while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
    		}
    		#undef tc
    }F;
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	for (F.read(t);t;--t)
    	{
    		RI i; for (F.read(n),i=1;i<=n;++i)
    		F.read(x),++dlt[max(i-x,1)],--dlt[min(i+x,n)+1];
    		for (i=1;i<=n;++i) dlt[i]+=dlt[i-1],F.read(h[i]);
    		sort(dlt+1,dlt+n+1); sort(h+1,h+n+1);
    		bool flag=1; for (i=1;i<=n;++i)
    		if (dlt[i]!=h[i]) { flag=0; break; }
    		for (i=1;i<=n+1;++i) dlt[i]=0;
    		puts(flag?"YES":"NO");
    	}
    	return 0;
    }
    

    E Guddu and his Mother

    我们发现如果一个区间([l,r])内所有数异或起来是(0)那么中间的点可以取区间长度-1的位置

    因此我们统计一下异或和为(0)的区间长度和即可,用树状数组统计一下即可

    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<algorithm>
    #define int long long
    #define RI register int
    #define CI const int&
    #define Tp template <typename T>
    using namespace std;
    typedef vector <int>::iterator VI;
    const int N=100005;
    int t,n,x,ret,stk[N],top; bool vis[N*10];
    vector <int> L[N*10],R[N*10]; long long ans;
    class FileInputOutput
    {
    	private:
    		static const int S=1<<21;
    		#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
    		char Fin[S],*A,*B;
    	public:
    		Tp inline void read(T& x)
    		{
    			x=0; char ch; while (!isdigit(ch=tc()));
    			while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
    		}
    		#undef tc
    }F;
    class Tree_Array
    {
    	private:
    		int bit[N];
    	public:
    		#define lowbit(x) x&-x
    		inline void add(RI x,CI y)
    		{
    			for (;x<=n;x+=lowbit(x)) bit[x]+=y;
    		}
    		inline int get(RI x,int ret=0)
    		{
    			for (;x;x-=lowbit(x)) ret+=bit[x]; return ret;
    		}
    		#undef lowbit
    }NUM,SUM;
    signed main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	for (F.read(t);t;--t)
    	{
    		RI i,j; for (F.read(n),vis[stk[top=1]=ret=0]=i=1;i<=n;++i)
    		{
    			L[ret].push_back(i); F.read(x);
    			ret^=x; R[ret].push_back(i);
    			if (!vis[ret]) stk[++top]=ret,vis[ret]=0;
    		}
    		for (ans=0,i=1;i<=top;++i)
    		{
    			for (VI it=L[stk[i]].begin();it!=L[stk[i]].end();++it)
    			NUM.add(*it,1),SUM.add(*it,*it);
    			for (VI it=R[stk[i]].begin();it!=R[stk[i]].end();++it)
    			ans+=(*it)*NUM.get(*it)-SUM.get(*it);
    			for (VI it=L[stk[i]].begin();it!=L[stk[i]].end();++it)
    			NUM.add(*it,-1),SUM.add(*it,-(*it));
    			L[stk[i]].clear(); R[stk[i]].clear(); vis[stk[i]]=0;
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    

    F Encoding

    看到数据范围直接数位DP一下就好了

    定义(f_{i,j})表示当前处理完了前(i)位,上一位是(j)时的状态

    状态我们要记录两个,一个是合法的状态数,用来累计这一位的贡献,另一个就是总贡献数

    #include<cstdio>
    #include<cctype>
    #define RI register int
    #define CI const int&
    #define Tp template <typename T>
    using namespace std;
    const int N=100005,mod=1e9+7;
    int t,n,a[N],pw[N]; char ch;
    struct data
    {
    	int num,sum;
    	inline data(CI Num=-1,CI Sum=-1)
    	{
    		num=Num; sum=Sum;
    	}
    }f[N][10];
    inline bool operator ~ (const data& x)
    {
    	return ~x.num&&~x.sum;
    }
    class FileInputOutput
    {
    	private:
    		static const int S=1<<21;
    		#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
    		char Fin[S],*A,*B;
    	public:
    		Tp inline void read(T& x)
    		{
    			x=0; char ch; while (!isdigit(ch=tc()));
    			while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
    		}
    		inline void get_digit(char& ch)
    		{
    			while (!isdigit(ch=tc()));
    		}
    		#undef tc
    }F;
    inline void inc(int& x,CI y)
    {
    	if ((x+=y)>=mod) x-=mod;
    }
    inline data MDFS(CI nw,CI lst,CI cl)
    {
    	if (!~nw) return data(1,0); if (!cl&&~f[nw][lst]) return f[nw][lst];
    	data ret(0,0); int lim=cl?a[nw]:9; for (RI i=0;i<=lim;++i)
    	{
    		data nxt=MDFS(nw-1,i,cl&&(i==a[nw]));
    		inc(ret.num,nxt.num); inc(ret.sum,nxt.sum);
    		if (i!=lst) inc(ret.sum,1LL*i*pw[nw]%mod*nxt.num%mod);
    	}
    	if (cl) return ret; return f[nw][lst]=ret;
    }
    signed main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	RI i,j; for (pw[0]=i=1;i<N;++i) pw[i]=10LL*pw[i-1]%mod;
    	for (F.read(t);t;--t)
    	{
    		for (F.read(n),i=n-1;~i;--i)
    		F.get_digit(ch),a[i]=ch&15;
    		for (--a[i=0];a[i]<0;++i) a[i]+=10,--a[i+1];
    		if (!a[n-1]) --n;	for (i=0;i<=n;++i) for (j=0;j<10;++j)
    		f[i][j]=data(); int dlt=MDFS(n-1,0,1).sum;
    		for (F.read(n),i=n-1;~i;--i)
    		F.get_digit(ch),a[i]=ch&15;
    		for (i=0;i<=n;++i) for (j=0;j<10;++j)
    		f[i][j]=data(); int ret=MDFS(n-1,0,1).sum;
    		printf("%d
    ",(ret-dlt+mod)%mod);
    	}
    	return 0;
    }
    

    G Chef and Gordon Ramsay

    首先有一个很套路的统计方法,我们考虑将每个点作为中间点时计算答案

    那么我们分类讨论一下三种情况,发现其实只需要统计出子树内小于(大于)它的数的个数和子树外小于(大于)它的数的个数

    子树内我们套路的线段树合并一下就能求出来了,然后减一减就得到了外面的,将方案乘起来就好了

    注意中间点为(1)(3)时算点对要除以(2)

    #include<cstdio>
    #include<cctype>
    #define RI register int
    #define CI const int&
    #define Tp template <typename T>
    using namespace std;
    const int N=100005;
    struct edge
    {
    	int to,nxt;
    }e[N<<1]; int t,head[N],n,p1,p2,p3,cnt,x,y,rt[N]; long long ans;
    class FileInputOutput
    {
    	private:
    		static const int S=1<<21;
    		#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
    		char Fin[S],*A,*B;
    	public:
    		Tp inline void read(T& x)
    		{
    			x=0; char ch; while (!isdigit(ch=tc()));
    			while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
    		}
    		#undef tc
    }F;
    inline void addedge(CI x,CI y)
    {
    	e[++cnt]=(edge){y,head[x]}; head[x]=cnt;
    	e[++cnt]=(edge){x,head[y]}; head[y]=cnt;
    }
    class Segment_Tree
    {
    	private:
    		static const int P=20;
    		struct segment
    		{
    			int ch[2],sum;
    		}node[N*P<<1]; int tot;
    	public:
    		#define TN CI l=1,CI r=n
    		#define LS l,mid
    		#define RS mid+1,r
    		#define lc(x) node[x].ch[0]
    		#define rc(x) node[x].ch[1]
    		#define S(x) node[x].sum
    		inline void insert(int& now,CI pos,TN)
    		{
    			if (!now) now=++tot; ++S(now); if (l==r) return; int mid=l+r>>1;
    			if (pos<=mid) insert(lc(now),pos,LS); else insert(rc(now),pos,RS);
    		}
    		inline int merge(CI x,CI y,TN)
    		{
    			if (!x||!y) return x|y; int now=++tot; S(now)=S(x)+S(y);
    			if (l==r) return now; int mid=l+r>>1;
    			lc(now)=merge(lc(x),lc(y),LS); rc(now)=merge(rc(x),rc(y),RS); return now;
    		}
    		inline int query(CI now,CI beg,CI end,TN)
    		{
    			if (!now) return 0; if (beg<=l&&r<=end) return S(now);
    			int mid=l+r>>1,ret=0; if (beg<=mid) ret+=query(lc(now),beg,end,LS);
    			if (end>mid) ret+=query(rc(now),beg,end,RS); return ret;
    		}
    		inline void clear(void)
    		{
    			for (RI i=1;i<=tot;++i) lc(i)=rc(i)=S(i)=0; tot=0;
    		}
    		#undef TN
    		#undef LS
    		#undef RS
    		#undef lc
    		#undef rc
    }SEG;
    #define to e[i].to
    inline void DFS(CI now=1,CI fa=0)
    {
    	RI i; SEG.insert(rt[now],now); for (i=head[now];i;i=e[i].nxt)
    	if (to!=fa) DFS(to,now),rt[now]=SEG.merge(rt[now],rt[to]);
    	if (p2==1)
    	{
    		int mxnum=SEG.query(rt[now],now+1,n); long long ret=0;
    		for (i=head[now];i;i=e[i].nxt) if (to!=fa)
    		{
    			int cur=SEG.query(rt[to],now+1,n);
    			ret+=1LL*cur*(mxnum-cur);
    		}
    		ans+=(ret>>1LL)+1LL*mxnum*(n-now-mxnum);
    	} else if (p2==2)
    	{
    		int mxnum=SEG.query(rt[now],now+1,n),minum=SEG.query(rt[now],1,now-1);
    		for (i=head[now];i;i=e[i].nxt) if (to!=fa)
    		ans+=1LL*SEG.query(rt[to],now+1,n)*(minum-SEG.query(rt[to],1,now-1));
    		ans+=1LL*mxnum*(now-1-minum); ans+=1LL*minum*(n-now-mxnum);
    	} else
    	{
    		int minum=SEG.query(rt[now],1,now-1); long long ret=0;
    		for (i=head[now];i;i=e[i].nxt) if (to!=fa)
    		{
    			int cur=SEG.query(rt[to],1,now-1);
    			ret+=1LL*cur*(minum-cur);
    		}
    		ans+=(ret>>1LL)+1LL*minum*(now-1-minum);
    	}
    }
    #undef to
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	for (F.read(t);t;--t)
    	{
    		RI i; F.read(n); F.read(p1); F.read(p2); F.read(p3);
    		for (ans=0,i=1;i<n;++i) F.read(x),F.read(y),addedge(x,y);
    		for (DFS(),printf("%lld
    ",ans),cnt=0,i=1;i<=n;++i) head[i]=0;
    		for (SEG.clear(),i=1;i<=n;++i) rt[i]=0;
    	}
    	return 0;
    }
    

    Postscript

    讲道理Div2的题目还是偏简单的,全部做下来两三个小时就好了

    希望到时候打Div1别被完虐吧QWQ

  • 相关阅读:
    阿里云公网IP不能使用
    Python2 socket TCPServer 多线程并发 超时关闭
    Python2 socket 多线程并发 ThreadingTCPServer Demo
    Python2 socket 多线程并发 TCPServer Demo
    Python socket TCPServer Demo
    Python socket server demo
    jsp注释方式
    面试小结(java基础)
    java 多线程sleep和wait的区别
    Java中Runnable和Thread的区别
  • 原文地址:https://www.cnblogs.com/cjjsb/p/11342591.html
Copyright © 2011-2022 走看看