• Codeforces Round #475 Div. 1


      B:当n是偶数时无解,因为此时树中有奇数条边,而我们每次都只能删除偶数条。当n是奇数时一定有解,因为此时不可能所有点度数都为奇数,只要找到一个度数为偶数的点,满足将它删掉后,各连通块大小都为奇数就可以了。考虑如何证明这样的点一定存在。钦定一个根后,考虑找到一个度数为偶数的点,满足子树内点度数均为奇数。这样该点的所有儿子的子树都有奇数个点, 因为删掉该点后每个子树内只有一个点度数为偶数。又因为删掉这个点后该树剩下偶数个点和偶数个连通块,所以该点父亲所在连通块也有奇数个点。

      于是只需要先自底向上删掉度数为偶数的点,再将剩余每棵树自顶向下删除即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 200010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n,p[N],fa[N],degree[N],t,root;
    struct data{int to,nxt;
    }edge[N<<1];
    void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
    void dfs(int k)
    {
    	for (int i=p[k];i;i=edge[i].nxt)
    	{
    		dfs(edge[i].to);
    		degree[k]+=(degree[edge[i].to]%2==0);
    	}
    	if ((degree[k]&1)==(k!=root)) printf("%d
    ",k);
    }
    void dfs2(int k)
    {
    	if ((degree[k]&1)!=(k!=root)) printf("%d
    ",k);
    	for (int i=p[k];i;i=edge[i].nxt) dfs2(edge[i].to);
    }
    signed main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("b.in","r",stdin);
    	freopen("b.out","w",stdout);
    #endif
    	n=read();
    	for (int i=1;i<=n;i++)
    	{
    		fa[i]=read();
    		if (fa[i]) addedge(fa[i],i);
    		else root=i;
    	}
    	if (n%2==0) {cout<<"NO";return 0;}
    	cout<<"YES"<<endl;
    	dfs(root);
    	dfs2(root);
    	return 0;
    	//NOTICE LONG LONG!!!!!
    }

      C:对于每种矩形宽,找出其各种矩形长的出现次数。如果对某两种宽,其矩形长出现次数的比例不同,显然无解。然后对所有出现次数取gcd即可,gcd的因子数即为答案,即考虑每一行各种矩形长究竟出现了多少次。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 200010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    ll gcd(ll n,ll m){return m==0?n:gcd(m,n%m);}
    ll read()
    {
    	ll x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n,tot;
    ll ans;
    struct data
    {
    	ll x,y,z;
    	bool operator <(const data&a) const
    	{
    		return x<a.x||x==a.x&&y<a.y;
    	}
    }a[N];
    void error(){cout<<0;exit(0);}
    signed main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("c.in","r",stdin);
    	freopen("c.out","w",stdout);
    #endif
    	n=read();
    	for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(),a[i].z=read(),ans=gcd(ans,a[i].z);
    	sort(a+1,a+n+1);
    	int len=0;
    	for (int i=1;i<=n;i++) if (a[i].x==a[1].x) len++;else break;
    	if (n%len) error();
    	for (int i=1;i<=n;i+=len)
    	{
    		ll x=0;if (a[i].x==a[i-1].x) error();
    		for (int j=i;j<i+len;j++)
    		{
    			x=gcd(x,a[j].z);
    			if (i>len&&(a[j].x!=a[i].x||a[j].y!=a[j-len].y)) error();
    		}
    		for (int j=i;j<i+len;j++)
    		{
    			a[j].z/=x;
    			if (i>len&&a[j].z!=a[j-len].z) error();
    		}
    	}
    	for (ll i=1;i*i<=ans;i++)
    	if (ans%i==0)
    	{
    		tot++;
    		if (i*i!=ans) tot++;
    	}
    	cout<<tot;
    	return 0;
    	//NOTICE LONG LONG!!!!!
    } 
    

      D:注意到询问串长度不同的询问只有O(√n)种,也就是说只有O(n√n)个子串是有用的。显然可以把这些子串找到暴力哈希,但不优美。

      考虑SA,离线,将所有询问串和原串拼起来,从大到小按height数组合并,回答询问时找到其在名次数组上所在集合(仅考虑原串中的位置),即要求集合中挑出k个元素的极差最小值。同时注意到题面里还说保证询问串不同,那么每次暴力sort一下所在集合复杂度就是对的。这样带了个log,不sort随便改一下就可以去掉了。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define ll long long
    #define N 300010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    ll gcd(ll n,ll m){return m==0?n:gcd(m,n%m);}
    ll read()
    {
    	ll x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n,m,a[N],sa[N],sa2[N],rk[N<<1],cnt[N],tmp[N<<1],v[N],h[N],ans[N],fa[N],t;
    vector<int> pos[N],S[N];
    struct data
    {
    	int i,k,begin,end;
    	bool operator <(const data&a) const
    	{
    		return end-begin>a.end-a.begin;
    	}
    }q[N];
    char s[N];
    void make(int n)
    {
    	int m=27;
    	for (int i=1;i<=n;i++) cnt[rk[i]=a[i]]++;
    	for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
    	for (int i=n;i>=1;i--) sa[cnt[rk[i]]--]=i;
    	for (int k=1;k<=n;k<<=1)
    	{
    		int p=0;
    		for (int i=n-k+1;i<=n;i++) sa2[++p]=i;
    		for (int i=1;i<=n;i++) if (sa[i]>k) sa2[++p]=sa[i]-k;
    		memset(cnt,0,m+1<<2);
    		for (int i=1;i<=n;i++) cnt[rk[i]]++;
    		for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
    		for (int i=n;i>=1;i--) sa[cnt[rk[sa2[i]]]--]=sa2[i];
    		memcpy(tmp,rk,sizeof(tmp));
    		p=1;rk[sa[1]]=1;
    		for (int i=2;i<=n;i++)
    		{
    			if (tmp[sa[i]]!=tmp[sa[i-1]]||tmp[sa[i]+k]!=tmp[sa[i-1]+k]) p++;
    			rk[sa[i]]=p;
    		}
    		if (p==n) break;
    		m=p;
    	}
    	for (int i=1;i<=n;i++)
    	{
    		v[i]=max(v[i-1]-1,0);
    		while (a[i+v[i]]==a[sa[rk[i]-1]+v[i]]) v[i]++;
    	}
    	for (int i=1;i<=n;i++) h[i]=v[sa[i]],pos[h[i]].push_back(i);
    }
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    signed main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("d.in","r",stdin);
    	freopen("d.out","w",stdout);
    #endif
    	scanf("%s",s+1);t=n=strlen(s+1);
    	for (int i=1;i<=n;i++) a[i]=s[i]-'a'+1;a[++t]=27;
    	m=read();
    	for (int i=1;i<=m;i++)
    	{
    		q[i].k=read(),q[i].i=i;
    		q[i].begin=++t;
    		scanf("%s",s+1);
    		int u=strlen(s+1);
    		for (int j=1;j<=u;j++) a[t++]=s[j]-'a'+1;
    		q[i].end=--t;
    	}
    	sort(q+1,q+m+1);
    	make(t);
    	for (int i=1;i<=t;i++) fa[i]=i;
    	int cur=0;
    	for (int i=t;i>=1;i--)
    	{
    		for (int j=0;j<pos[i].size();j++) fa[find(pos[i][j])]=find(pos[i][j]-1);
    		if (q[cur+1].end-q[cur+1].begin+1==i)
    		{
    			for (int j=1;j<=t;j++) S[j].clear();
    			for (int j=1;j<=n;j++) S[find(rk[j])].push_back(j);
    			while (cur<m&&q[cur+1].end-q[cur+1].begin+1==i)
    			{
    				cur++;int x=find(rk[q[cur].begin]);
    				if (S[x].size()<q[cur].k) {ans[q[cur].i]=-1;continue;}
    				ans[q[cur].i]=n;
    				for (int j=0;j<S[x].size()+1-q[cur].k;j++)
    				ans[q[cur].i]=min(ans[q[cur].i],S[x][j+q[cur].k-1]-S[x][j]+q[cur].end-q[cur].begin+1);
    			}
    		}
    	}
    	for (int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    	return 0;
    	//NOTICE LONG LONG!!!!!
    } 
    

      

  • 相关阅读:
    【emWin】例程二十:窗口对象——Dropdown
    【30集iCore3_ADP出厂源代码(ARM部分)讲解视频】30-11层驱动之FSMC
    【30集iCore3_ADP出厂源代码(ARM部分)讲解视频】30-10底层驱动之I2C
    【emWin】例程十九:窗口对象——Checkbox
    【iCore3应用】基于iCore3双核心板的编码器应用实例
    【emWin】例程十八:jpeg图片显示
    【GMT43液晶显示模块】发布原理图、出厂代码
    【iCore3应用开发平台】发布 iCore3 应用开发平台出厂代码rev0.0.6
    【30集iCore3_ADP出厂源代码(ARM部分)讲解视频】30-9底层驱动之USART
    【6集iCore3_ADP触摸屏驱动讲解视频】6-6 底层驱动之触摸操作
  • 原文地址:https://www.cnblogs.com/Gloid/p/10422996.html
Copyright © 2020-2023  润新知