zoukankan      html  css  js  c++  java
  • AtCoder Grand Contest 034

    一直很想找几套数字有特殊意义的考试题做做,终于找到时间了。

    其实个人认为(Atcoder)上的题目比较思维化,有点意思……(主要是比(Codeforces)好看)

    Atcoder Grand Contest 034 entry

    ( ext{A - Kenken Race})

    考虑两种情况:

    (1.)(a<bquad c<d),则只要分别可以到达即可。

    (2.)否则,只需在(b-1)(d+1)的路上有长度大于等于(3)的一串空格即可。

    代码如下,实现简单,思路简单:

    #include<bits/stdc++.h>
    using namespace std;
    #define inf 1e9
    const int maxn=2e5+10;
    const int mod=1e9+7;
    inline 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-'0';c=getchar();}
    	return x*f;
    }
    int n,a,b,c,d,p[maxn];
    int f1[maxn],f2[maxn];
    int main(){
    	n=read();
    	a=read(),b=read();
    	c=read(),d=read();
    	for(int i=1;i<=n;i++)
    		p[i]=getchar()=='.';
    	f1[a]=f2[b]=1;
    	for(int i=a+1;i<=c;i++)
    		f1[i]=(p[i]&(f1[i-1]|f1[i-2]));
    	for(int i=b+1;i<=d;i++)
    		f2[i]=(p[i]&(f2[i-1]|f2[i-2]));
    	if(!f1[c]||!f2[d]||c==d)return puts("No"),0;
    	if(c<d)return puts("Yes"),0;
    	int cnt=0;
    	for(int i=b-1;i<=d+1;i++)
    		if(!p[i]){if(cnt>=3)return puts("Yes"),0;cnt=0;}
    		else cnt++;
    	if(cnt>=3)puts("Yes");
    	else puts("No");
    	return 0;
    }
    

    正好(34)行呵(真不戳)。

    ( ext{B - ABC})

    个人觉得样例(1)的提示性有点强。

    结论就是一个(ABC)的贡献是其前导(A)的个数,操作过程样例(1)解释都给了。

    那么简单维护一下前导(A)统计答案即可,记得开(long long)

    代码如下,仅供参考:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define inf 1e9
    const int maxn=2e5+10;
    const int mod=1e9+7;
    int n,cnt,pos,tot;
    char s[maxn];
    inline 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-'0';c=getchar();}
    	return x*f;
    }
    signed main(){
    	scanf("%s",s+1);
    	n=strlen(s+1),pos=1;
    	while(pos<=n){
    		//printf("%d %d %d
    ",pos,cnt,tot);
    		if(s[pos]=='A'&&s[pos+1]=='B'&&s[pos+2]=='C'){
    			s[pos+2]='A';cnt+=1+tot;pos+=2;
    		}else if(s[pos]=='A')tot++,pos++;
    		else tot=0,pos++;
    	}
    	printf("%lld
    ",cnt);
    	return 0;
    }
    

    ( ext{C - Tests})

    二分答案,利用一次函数的单调性,枚举。

    时间复杂度(Theta(nlogn))

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int maxn=2e5+10;
    const int mod=1e9+7;
    int n,k,sum;
    struct node{int l,r,b,f;}p[maxn];
    inline int cmp(node x,node y){return x.f>y.f;}
    inline 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-'0';c=getchar();}
    	return x*f;
    }
    int pre[maxn];
    inline int calc(int id,int x){
    	if(x<=p[id].b)return x*p[id].l;
    	return p[id].b*p[id].l+p[id].r*(x-p[id].b);
    }
    inline bool check(int val){
    	int t=val/k,q=val%k;
    	int res=0;
    	for(int i=1;i<=n;i++)
    		if(i<=t)res=max(res,pre[t+1]-p[i].f+calc(i,q));
    		else res=max(res,pre[t]+calc(i,q));
    	return res>=sum;
    }
    signed main(){
    	n=read(),k=read();
    	for(int i=1;i<=n;i++){
    		p[i].b=read();
    		p[i].l=read(),p[i].r=read();
    		sum+=p[i].b*p[i].l;
    		p[i].f=calc(i,k);
    	}
    	sort(p+1,p+1+n,cmp);
    	int l=0,r=0;
    	for(int i=1;i<=n;i++)
    		r+=p[i].b;
    	for(int i=1;i<=n;i++)
    		pre[i]=pre[i-1]+p[i].f;
    	int ans=r;
    	while(l<=r){
    		int mid=(l+r)>>1;
    		if(check(mid))ans=mid,r=mid-1;
    		else l=mid+1;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    

    ( ext{D - Manhattan Max Matching})

    显然使用费用流,但朴素建边会(T)飞,考虑建虚点优化建边。

    显然如果要将(a(x_a,y_a))上的点与(b(x_b,y_b))上的点配对的话,其代价为(dis_{a,b}=|a_x-b_x|+|a_y-b_y|)

    这个式子有四种可能,如下:

    (a_x-b_x+a_y-b_yquad)(a_x+a_y)(-b_x-b_y)

    (a_x-b_x+b_y-a_yquad)(a_x-a_y)(-b_x+b_y)

    (b_x-a_x+a_y-b_yquad)(-a_x+a_y)(b_x-b_y)

    (b_x-a_x+b_y-a_yquad)(-a_x-a_y)(b_x+b_y)

    发现(dis)即这四个值中的最大值,也是最小值的相反数。

    故我们建四个虚点,分别连每个点的(x+y)(x-y)(-x+y)(-x-y)

    跑最小费用最大流时一定会走两点欧几里得距离的相反数。

    故跑一遍费用流,输出最小费用的相反数即可。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define inf 0x7f
    const int maxn=1e5+100;
    int beg[maxn],nex[maxn],to[maxn],f[maxn],c[maxn],e,mf,mc;
    void add(int x,int y,int z,int d){
    	nex[e]=beg[x];beg[x]=e;
    	to[e]=y;f[e]=z;c[e]=d;e++;
    }
    int n,m,st,ed,dis[maxn],vis[maxn],pre[maxn],val[maxn],flow[maxn];
    queue<int>q;
    int spfa(){
    	memset(dis,inf,sizeof(dis));
    	memset(flow,inf,sizeof(flow));
    	memset(vis,0,sizeof(vis));
    	dis[st]=0;pre[ed]=-1;vis[st]=1;
    	q.push(st);
    	while(!q.empty()){
    		int x=q.front();
    		q.pop();
    		vis[x]=0;
    		for(int i=beg[x];~i;i=nex[i]){
    			int t=to[i];
    			if(f[i]&&dis[t]>dis[x]+c[i]){
    				dis[t]=dis[x]+c[i];
    				pre[t]=x;val[t]=i;
    				flow[t]=min(flow[x],f[i]);
    				if(!vis[t]){
    					vis[t]=1;
    					q.push(t);
    				}
    			}
    		}
    	}
    	return pre[ed]!=-1;
    }
    signed main(){
    	cin>>n;
    	int x,y,z,p1,p2,p3,p4;
    	memset(beg,-1,sizeof(beg));
    	st=n+n+1;ed=st+1;
    	p1=ed+1,p2=p1+1,p3=p2+1,p4=p3+1;
    	for(int i=1;i<=n;i++){
    		scanf("%lld%lld%lld",&x,&y,&z);
    		add(st,i,z,0);add(i,st,0,0);
    		add(i,p1,inf,x+y);add(p1,i,0,-x-y);
    		add(i,p2,inf,x-y);add(p2,i,0,y-x);
    		add(i,p3,inf,y-x);add(p3,i,0,x-y);
    		add(i,p4,inf,-x-y);add(p4,i,0,x+y);
    	}
    	for(int i=1;i<=n;i++){
    		scanf("%lld%lld%lld",&x,&y,&z);
    		add(i+n,ed,z,0);add(ed,i+n,0,0);
    		add(p1,i+n,inf,-x-y);add(i+n,p1,0,x+y);
    		add(p2,i+n,inf,y-x);add(i+n,p2,0,x-y);
    		add(p3,i+n,inf,x-y);add(i+n,p3,0,y-x);
    		add(p4,i+n,inf,x+y);add(i+n,p4,0,-x-y);
    	}
    	while(spfa()){
    		int now=ed;
            mf+=flow[ed];
            mc+=flow[ed]*dis[ed];
            while(now!=st){
                f[val[now]]-=flow[ed];
                f[val[now]^1]+=flow[ed];
                now=pre[now];
            }
    	}
    	printf("%lld
    ",-mc);
    	return 0;
    }
    

    ( ext{E - Complete Compress})

    神仙题,居然在冬令营上被讲到了。

    考虑建成一个集合互相抵消的模。

    我们要将这些集合最终抵消完,考虑最大的集合。

    若这个集合的数量小于等于半数,则可以消集合大小的半数次,即([frac{size}{2}])

    若这个集合的数量大于半数,则用外部的消完后本集合内再相互抵消。

    每个点做一遍树形(dp),复杂度(Theta(n^2))

    #include<bits/stdc++.h>
    using namespace std;
    #define inf 1e9
    const int maxn=2e3+10;
    const int mod=1e9+7;
    int n,a[maxn],cnt;
    inline 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-'0';c=getchar();}
    	return x*f;
    }
    string s;
    int beg[maxn],nex[maxn<<1],to[maxn<<1],e;
    inline void add(int x,int y){
    	e++;nex[e]=beg[x];
    	beg[x]=e;to[e]=y;
    }
    int val[maxn];
    int dis[maxn],f[maxn],ans=inf;
    inline void solve(int x,int fa){
    	val[x]=a[x];dis[x]=0;
    	int son=0;
    	for(int i=beg[x];i;i=nex[i]){
    		int t=to[i];
    		if(t==fa)continue;
    		solve(t,x);
    		val[x]+=val[t];
    		dis[x]+=(dis[t]+=val[t]);
    		if(dis[t]>dis[son])son=t;
    	}
    	if(!son)return void(f[x]=0);
    	if(dis[x]>=2*dis[son])f[x]=dis[x]/2;
    	else f[x]=dis[x]-dis[son]+min(f[son],(dis[son]*2-dis[x])/2);
    }
    int main(){
    	n=read();cin>>s;
    	for(int i=1;i<=n;i++)
    		if(s[i-1]=='1')a[i]=1,cnt++;
    	int x,y;
    	for(int i=1;i<n;i++){
    		x=read(),y=read();
    		add(x,y),add(y,x);
    	}
    	for(int i=1;i<=n;i++){
    		solve(i,0);
    		if(!(dis[i]&1)&&f[i]==dis[i]/2)
    			ans=min(ans,dis[i]/2);
    	}
    	printf("%d
    ",ans==inf?-1:ans);
    	return 0;
    }
    

    ( ext{F - RNG and XOR})

    神仙(fwt),基本不可做,操作仙得一(mp)

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int maxn=(1<<18)+10;
    const int mod=998244353;
    const int inv2=(mod+1)/2;
    inline 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-'0';c=getchar();}
    	return x*f;
    }
    inline int ksm(int x,int y){
    	int res=1;
    	while(y){
    		if(y&1)res=res*x%mod;
    		x=x*x%mod;y>>=1;
    	}
    	return res;
    }
    int n,sum,len,p[maxn],q[maxn],f[maxn];
    inline void fwt(int *a,int n,int flag){
    	for(int i=2;i<=n;i<<=1)
    		for(int j=0,p=i>>1;j<n;j+=i)
    			for(int k=j;k<j+p;k++){
    				int x=a[k],y=a[k+p];
    				a[k]=(x+y)%mod;
    				a[k+p]=(x+mod-y)%mod;
    				if(!flag){
    					a[k]=a[k]*inv2%mod;
    					a[k+p]=a[k+p]*inv2%mod;
    				}
    			}
    }
    signed main(){
    	n=read();len=1<<n;
    	for(int i=0;i<len;i++){
    		p[i]=read();
    		sum=(sum+p[i])%mod;
    	}
    	sum=ksm(sum,mod-2);
    	for(int i=0;i<len;i++)
    		p[i]=p[i]*sum%mod;
    	q[0]=len-1;p[0]+=mod-1;
    	for(int i=1;i<len;i++)
    		q[i]=mod-1;
    	fwt(p,len,1);fwt(q,len,1);
    	for(int i=0;i<len;i++)
    		f[i]=q[i]*ksm(p[i],mod-2)%mod;
    	fwt(f,len,0);
    	int tmp=mod-f[0];
    	for(int i=0;i<len;i++)
    		printf("%lld
    ",(f[i]+tmp)%mod);
    	return 0;
    }
    
  • 相关阅读:
    IHttpHandler and HttpModule
    sql page reship
    prototype
    google search engine theory
    ghost
    sql split
    Missing you is a kind of my deeppain in my life
    file control
    a story of c#(reship)
    teacher and student(reship)
  • 原文地址:https://www.cnblogs.com/syzf2222/p/14167461.html
Copyright © 2011-2022 走看看