zoukankan      html  css  js  c++  java
  • WHU校赛2019(网络赛) 解题报告(CCNU_你们好强啊我们都是面包手) Apare_xzc

    WHU校赛2019(网络赛) 解题报告

    CCNU_你们好强啊我们都是面包手(xzc zx lj)


    战况: 比赛时3题,排名57,现在5题了

    题目链接: WHU校赛2019 <-戳这里


    以下题目按难度顺序递增叙述


    B.DrunkHamster
    求两点之间距离的平方,签到题

    /*
    Apr/07/2019 13:49UTC+8	
    CCNU_你们好强啊我们都是面包手	
    B - DrunkHamster	
    GNU C++17	Accepted	30 ms	0 KB
    */
    #include <bits/stdc++.h>
    #define For(i,a,b) for(register int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
    #define Mst(a,b) memset(a,(b),sizeof(a))
    #define LL long long
    #define MP make_pair
    #define pb push_back
    using namespace std;
    const int maxn = 1e5+100;
    void solve(int x,int y)
    {
    	LL ans = (1ll*x*x+1ll*y*y);
    	cout<<ans<<endl;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        LL x,y,z;
    	int T,n;
    	cin>>T;
    	int ca = 0;
    	while(T--)
    	{
    		x = y = 0;
    		scanf("%d",&n);
    		For(i,0,n-1)
    		{
    			scanf("%I64d",&z);	
    			if(i%4==0) y += z;
    			else if(i%4==1) x+=z;
    			else if(i%4==2) y-=z;
    			else x-=z;
    		}	
    		printf("Case #%d:",++ca);
    		solve(x,y);
    	} 
        return 0;
    }
    

    E.Egnima
    简单模拟,搞个map或者数组对应,比较字符串即可

    /*
    Apr/07/2019 14:03UTC+8	
    CCNU_你们好强啊我们都是面包手	
    E - Egnima	
    GNU C++17	Accepted	31 ms	2100 KB
    */
    #include <bits/stdc++.h>
    #define For(i,a,b) for(register int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
    #define Mst(a,b) memset(a,(b),sizeof(a))
    #define LL long long
    #define MP make_pair
    #define pb push_back
    using namespace std;
    const int maxn = 1e6+100;
    char a[] = "abcdefghijklmnopqrstuvwxyz";
    char b[] = "22233344455566677778889999"; 
    map<char,char> mp;
    char num[maxn],str[maxn]; 
    int LenNum;
    bool ok()
    {
    	int len = strlen(str)-1;
    	if(len!=LenNum) return false;
    	For(i,0,len)
    	{
    		if(mp[str[i]]!=num[i]) return false;
    	}
    	return true;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        int len = strlen(a)-1;
        For(i,0,len)
        {
        	mp[a[i]] = b[i];
    	}
    	int T,n;
    	cin>>T;
    	int ca = 0;
    	while(T--)
    	{
    		printf("Case #%d:
    ",++ca);
    		scanf("%s",num);
    		LenNum = strlen(num)-1;
    		scanf("%d",&n);
    		For(ca,1,n)
    		{
    			scanf("%s",str);
    			if(ok())
    			{
    				printf("Maybe..
    ");
    			}
    			else
    			{
    				printf("How could that be possible?
    ");
    			}
    		}
    	} 
        return 0;
    }
    

    D.Dandelion

    卡特兰数 C(m+n-1,n-1)-C(m+n-1,m-1))
    预处理阶乘以及阶乘的逆元即可
    打比赛的前一天我在牛客上写了道类似的题
    感谢lj正确的公式,是我写呲了,忘记%mod+mod%mod,wa了一发,我的锅

    /*
    Apr/07/2019 14:44 UTC+8	
    CCNU_你们好强啊我们都是面包手	
    D - Dandelion	
    GNU C++17  Accepted 62ms 31300 KB
    */
    #include <bits/stdc++.h>
    #define For(i,a,b) for(register int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
    #define Mst(a,b) memset(a,(b),sizeof(a))
    #define LL long long
    #define MP make_pair
    #define pb push_back
    using namespace std;
    const int maxn = 2e6+100;
    const int mod = 1e9+7;
    LL r[maxn];
    LL fac[maxn];
    LL fast_pow(LL a,LL b);
    void init();
    LL C(int n,int m); 
    int main()
    {
       // freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        int T,m,n;
        init();
        cin>>T;
        while(T--)
        {
        	scanf("%d%d",&m,&n);
        	LL ans = ((C(m+n-1,max(m,n)-1)-C(m+n-1,min(m,n)-1))%mod+mod)%mod;
        	printf("%I64d
    ",abs(ans));
    	}
        
        return 0;
    }
    
    
    LL fast_pow(LL a,LL b)
    {
    	LL ans = 1;
    	while(b)
    	{
    		if(b&1) ans = ans*a%mod;
    		a = a*a%mod;
    		b>>=1;	
    	}
    	return ans; 
    } 
    void init()
    {
    	fac[0] = 1;
    	r[0] = 1;
    	For(i,1,2000000) fac[i] = fac[i-1]*i%mod;
    	r[2000000] = fast_pow(fac[2000000],mod-2);
    	Rep(i,1999999,1)
    		r[i] = r[i+1]*(i+1)%mod;
    		
    }
    LL C(int n,int m)
    {
    	if(n<m||m<0) return 0;
    	return fac[n]*r[m]%mod*r[n-m]%mod;
    }
    

    C.Store

    题意:
    n种货物
    M x y:在第x天买了第y种货物
    D x y: 查询在之前比x小的天数中卖过的货物>=y的最小值
    1<=y<=n<=1e5 x<=1e9

    思路:

    • 线段树,把x离散化,按x建立线段树,线段树每个节点开一个set,存这个区间里已经卖出去的y(货物种类)
    • 单点更新,区间查询
    • 这题还不难,但比赛的时候作为数据结构手的我去搞没做过的主席树了… 还是我的锅,不过今天上算法课写了一发,补出来了

    /*
    Apr/08/2019 15:43UTC+8	
    CCNU_你们好强啊我们都是面包手	
    C - Store	
    GNU C++17  Accepted	794 ms  61900 KB
    */
    #include <bits/stdc++.h>
    #define For(i,a,b) for(register int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
    #define Mst(a,b) memset(a,(b),sizeof(a))
    #define LL long long
    #define MP make_pair
    #define pb push_back
    using namespace std;
    const int maxn = 2e5+3;
    int a[maxn],p[maxn];
    set<int>::iterator it;
    struct SegmentTree{
    	set<int> s; 
    }tree[maxn<<2]; 
    struct Question{
    	char tp[2];
    	int x,y;
    }qu[maxn];
    void update(int left,int right,int tx,int ty,int pos=1)
    {
    	tree[pos].s.insert(ty);
    	if(left==right) return;
    	int mid = (left+right)>>1;
    	if(tx<=mid) update(left,mid,tx,ty,pos<<1);
    	else update(mid+1,right,tx,ty,pos<<1|1);
    }
    int query(int left,int right,int qx,int qy,int ty,int pos=1) 
    {
    	if(left>qy || right<qx) 
    	{
    		return -1;	
    	}
    	if(qx<=left && right<= qy)
    	{
    		it = tree[pos].s.lower_bound(ty);
    		if(it==tree[pos].s.end()) return -1;
    		return *it;
    	}
    	int mid = (left+right)>>1; 
    	int ansL = query(left,   mid,qx,qy,ty,pos<<1);
    	int ansR = query(mid+1,right,qx,qy,ty,pos<<1|1);
    	if(ansL==-1&&ansR==-1) return -1;
    	else if(ansL==-1) return ansR;
    	else if(ansR==-1) return ansL;
    	return min(ansL,ansR);
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        int n,Q;
        scanf("%d%d",&n,&Q); 
        For(i,1,Q)
        {
        	scanf("%s%d%d",qu[i].tp,&qu[i].x,&qu[i].y);
        	p[i] = qu[i].x;
    	}
    	sort(p+1,p+1+Q);
    	int Maxx = 0;
    	For(i,1,Q)
    	{
    		qu[i].x = lower_bound(p+1,p+1+Q,qu[i].x)-p;
    		Maxx = max(Maxx,qu[i].x);
    	}
    	For(i,1,Q)
    	{
    		if(qu[i].tp[0]=='M') update(1,Maxx,qu[i].x,qu[i].y);
    		else printf("%d
    ",query(1,Maxx,1,qu[i].x,qu[i].y));
    	}
        return 0;
    }
    

    F. Climb

    • 树上第K小板子题(不过这是第K大)
    • 今天学了一下,过了poj-2104,spoj-10628,学会了
    • LCA是我上上周学的,dfs+RMQ
    • 今天看卿爷和Y_Cl区间第K大的板子,感觉很好用
    • 于是根据主席树的原理,写出了树上第K大~
    • 这是我最近写的最长,开的数组最多的代码了
    /*
    Apr/08/2019 22:10UTC+8	
    CCNU_你们好强啊我们都是面包手	
    F - Climb	
    GNU C++17 Accepted	1294 ms	59200 KB
    */
    Apr/09/2019 06:22UTC+8	CCNU_你们好强啊我们都是面包手	F - Climb	GNU C++17	Accepted	1294 ms	59200 KB
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define For(i,a,b) for(register int i=(a);i<=(b);++i)
    #define Mst(a,b) memset(a,(b),sizeof(a))
    using namespace std;
    const int maxn = 1e5+20;
    int a[maxn],p[maxn],n,cnt;//p离散化 
    struct Edge{
    	int to,Next;
    }edge[maxn<<1];
    int head[maxn],totEdge;//邻接表 
    int First[maxn],sequence[maxn<<1],deep[maxn<<1];
    int father[maxn];
    bool vis[maxn]; //dfs 
    int Min[maxn<<1][20];
    int Log2[maxn<<1]={-1};
    struct Node{
    	Node * Lchild, * Rchild;
    	int sum;
    }node[maxn*20],*root[maxn*20];
    Node * update(int,int,int,Node*); 
    void build(); //建第一课空树(爷爷节点) 
    void initG(); //初始化邻接表 
    void addedge(int u,int v);
    void dfs(int x,int fa,int deep,int&);
    void getST(int n); 
    int LCA(int x,int y);
    int query(int,int,int,Node*,Node*,Node*,Node*);
    int main()
    {
    	//freopen("in.txt","r",stdin);
    	For(i,1,maxn*2-15) Log2[i] = Log2[i>>1]+1;
    	int T,m;scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%d%d",&n,&m);
    		For(i,1,n) scanf("%d",a+i), p[i] = a[i];
    		sort(p+1,p+1+n);
    		For(i,1,n) a[i] = lower_bound(p+1,p+1+n,a[i])-p;
    		int u,v;
    		initG();
    		For(i,2,n)
    		{
    			scanf("%d%d",&u,&v);
    			addedge(u,v);
    			addedge(v,u);
    		}	
    		build(); //先建一棵空树
    		Mst(vis,0); 
    		int cntOfSequence = 0;
    		dfs(1,0,1,cntOfSequence); //dfs生成树的同时,在父节点基础上建立新的线段树 
    		int k,lca;
    		getST(2*n-1); //线性预处理(nlogn) 
    		while(m--)
    		{
    			scanf("%d%d%d",&u,&v,&k); 
    			lca = LCA(u,v);
    			int totNum = deep[First[u]]+deep[First[v]]-deep[First[lca]]-deep[First[father[lca]]];
    			if(k>totNum) //询问的K大于这条路径上所有顶点的个数 
    			{
    				printf("-1
    ");
    				continue;
    			}
    			k = totNum - k+1;
    			printf("%d
    ",p[query(1,n,k,root[u],root[v],root[lca],root[father[lca]])]);
    		}	
    	} 
    	
    	return 0;	
    }
    
    void initG()
    {
    	Mst(head,-1);
    	totEdge = 0;
    }
    void addedge(int u,int v)
    {
    	edge[totEdge].to = v;
    	edge[totEdge].Next = head[u];
    	head[u] = totEdge++;
    }
    void dfs(int x,int fa,int dep,int &cntOfSeq)
    {
    	father[x] = fa;
    	vis[x] = true;
    	root[x] = update(1,n,a[x],root[fa]);
    	sequence[++cntOfSeq] = x;
    	deep[cntOfSeq] = dep;
    	First[x] = cntOfSeq;
    	for(int i=head[x];i!=-1;i=edge[i].Next)
    	{
    		int to = edge[i].to;
    		if(vis[to]) continue;
    		vis[to] = true;
    		dfs(to,x,dep+1,cntOfSeq);
    		sequence[++cntOfSeq] = x;
    		deep[cntOfSeq] = dep;
    	}
    }
    void getST(int n)
    {
    	For(i,1,n) Min[i][0] = i;
    	for(int j=1;(1<<j)<=n;++j)
    	{
    		for(int i=1;i+(1<<j)-1<=n;++i)
    		{
    			int a = Min[i][j-1];
    			int b = Min[i+(1<<(j-1))][j-1];
    			Min[i][j] = deep[a]>deep[b]?b:a;
    		}
    	}
    } 
    int LCA(int x,int y)
    {
    	x = First[x];
    	y = First[y];
    	if(x>y) swap(x,y);
    	int j = Log2[y-x+1];
    	int a = Min[x][j];
    	int b = Min[y-(1<<j)+1][j];
    	return deep[a]>deep[b]?sequence[b]:sequence[a];
    }
    Node * update(int left,int right,int v,Node * p)
    {
    	if(v<left||v>right) return p;
    	Node * t = &node[cnt++];
    	t->Lchild = p->Lchild;
    	t->Rchild = p->Rchild;
    	t->sum = p->sum + 1; 
    	if(left==right) return t;
    	int mid = (left+right)>>1;
    	t -> Lchild = update(left,mid,v,p->Lchild);
    	t -> Rchild = update(mid+1,right,v,p->Rchild);
    	return t;	
    }
    void build()
    {
    	cnt = 0;
    	root[0] = &node[cnt++];
    	root[0]->Lchild = root[0]->Rchild = root[0];
    	root[0]->sum = 0;
    }
    int query(int left,int right,int k,Node*ru,Node*rv,Node *rlca,Node*rfalca)
    {
    	if(left==right) return left;
    	int tot = ru->Lchild->sum + rv->Lchild->sum 
    	     - rlca->Lchild->sum - rfalca->Lchild->sum;
    	int mid = (left+right)>>1;
    	if(k<=tot) 
    		return query(left,mid,k,ru->Lchild,rv->Lchild,rlca->Lchild,rfalca->Lchild);
    	else 
    		return query(mid+1,right,k-tot,ru->Rchild,rv->Rchild,rlca->Rchild,rfalca->Rchild);
    }
    
    

    队友们,我们一起加油叭!
    好好训练,备战湘潭赛!
    fighting!


  • 相关阅读:
    108. Convert Sorted Array to Binary Search Tree
    107. Binary Tree Level Order Traversal II
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    104. Maximum Depth of Binary Tree
    103. Binary Tree Zigzag Level Order Traversal
    102. Binary Tree Level Order Traversal
    系统和进程相关信息
    文件I/0缓冲
    系统编程概念(文件系统mount等函数的使用)
  • 原文地址:https://www.cnblogs.com/Apare-xzc/p/12243653.html
Copyright © 2011-2022 走看看