zoukankan      html  css  js  c++  java
  • noip模拟测试23

    考试总结:这次考试,成绩和自己的预估分数差距有点大,问题主要是出在了第一题上,我当时读完题,就想到了线段树,很快就码完了,但是我当时没有想到的两个关键问题是:1.没有想到离散化 2.对于异或的情况没有分类讨论,导致我第一题爆零,其他的题还好,基本上拿到了自己预估的分数。这次考试的教训就是对于自己认为想到的正解多想想一些细节问题,不能想到啥就打啥。

    T1 联

    思路:很显然,一道线段树裸题,我的算法是记录每个区间的1的数量之和,最后查询的时候只需要按照先左后右的顺序查询当前区间里1的数量和区间长度的大小即可,但是注意对于异或的操作进行分类讨论,具体实现见代码:

    #include<bits/stdc++.h>
    #define int long long
    #define re register int
    #define ii inline int
    #define iv inline void
    #define lc (rt<<1)
    #define rc (rt<<1|1)
    #define mid ((l+r)>>1)
    using namespace std;
    const int N=1e7+10;
    const int M=1e6+10;
    int m,ty,ul,ur,cnt;
    int lsh[M];
    vector<int> v[N];
    struct CUN
    {
    	int sum,lazy;
    }use[N<<2];
    struct Segment_tree
    {
        iv pp(int rt)
        {
            use[rt].sum=use[lc].sum+use[rc].sum;
        }
        iv pd(int rt,int l,int r)
        {
            if(use[rt].lazy)
            {
                if(use[rt].lazy==1)
                {
                     use[lc].lazy=use[rc].lazy=use[rt].lazy;
                     use[lc].sum=mid-l+1;
                     use[rc].sum=r-mid;
                }
                else if(use[rt].lazy==2)
                {
                    use[lc].lazy=use[rc].lazy=use[rt].lazy;
                    use[lc].sum=0;
                    use[rc].sum=0;
                }
                else 
                {
                    if(use[lc].lazy==1)
                    {
                        use[lc].lazy=2;
                        use[lc].sum=0;
                    }
                    else if(use[lc].lazy==2)
                    {
                        use[lc].lazy=1;
                        use[lc].sum=mid-l+1;
                    }
                    else if(use[lc].lazy==3)
                    {
                        use[lc].lazy=0;
                        use[lc].sum=mid-l+1-use[lc].sum;
                    }
                    else
                    {
                        use[lc].lazy=3;
                        use[lc].sum=mid-l+1-use[lc].sum;
                    }
    
                    if(use[rc].lazy==1)
                    {
                        use[rc].lazy=2;
                        use[rc].sum=0;
                    }
                    else if(use[rc].lazy==2)
                    {
                        use[rc].lazy=1;
                        use[rc].sum=r-mid;
                    }
                    else if(use[rc].lazy==3)
                    {
                        use[rc].lazy=0;
                        use[rc].sum=r-mid-use[rc].sum;
                    }
                    else
                    {
                        use[rc].lazy=3;
                        use[rc].sum=r-mid-use[rc].sum;
                    }
                }
                use[rt].lazy=0;
            }
        }
    	iv change(int rt,int l,int r,int L,int R,int z)
        {
            if(L<=l&&r<=R)
            {
                if(z==1)
                {
                    use[rt].sum=r-l+1;
                    use[rt].lazy=1;
                }
                else if(z==2)
                {
                    use[rt].sum=0;
                    use[rt].lazy=2;
                }
                else
                {
                    if(use[rt].lazy==3)
                    {
                        use[rt].lazy=0;
                        use[rt].sum=r-l+1-use[rt].sum;
                    }
                    else if(use[rt].lazy==1)
                    {
                        use[rt].lazy=2;
                        use[rt].sum=0;
                    }
                    else if(use[rt].lazy==2)
                    {
                        use[rt].lazy=1;
                        use[rt].sum=r-l+1;
                    }
                    else
                    {
                        use[rt].sum=r-l+1-use[rt].sum;
                        use[rt].lazy=3;
                    }
                }
                return;
            }
            pd(rt,l,r);
            if(mid>=L)
            {
                change(lc,l,mid,L,R,z);
               
            }
            if(mid<R)
            {
                change(rc,mid+1,r,L,R,z);
            }
            pp(rt);
        }
        ii query(int rt,int l,int r)
        {
            if(l==r)
                return lsh[l];
            pd(rt,l,r);
            if(use[lc].sum<(mid-l+1))
                return query(lc,l,mid);
            return query(rc,mid+1,r);
        }
    }T;
    ii read()
    {
    	int x=0,f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-')
    			f=0;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<1)+(x<<3)+(ch^48);
    		ch=getchar();
    	}
    	return (f)?x:(-x);
    }
    signed main()
    {
    	m=read();
        int maxx=0;
    	for(re i=1;i<=m;i++)
    	{
    		ty=read();
    		ul=read();
    		ur=read();
            v[i].push_back(ty);
            v[i].push_back(ul);
            v[i].push_back(ur);
            maxx=max(maxx,ur);
            lsh[++cnt]=ul;
            lsh[++cnt]=ur;
            lsh[++cnt]=ul+1;
            lsh[++cnt]=ur+1;
    	}
        lsh[++cnt]=1;
        maxx++;
        sort(lsh+1,lsh+cnt+1);
        cnt=unique(lsh+1,lsh+cnt+1)-lsh-1;
        maxx=lower_bound(lsh+1,lsh+cnt+1,maxx)-lsh;
        for(re i=1;i<=m;i++)
        {
            v[i][1]=lower_bound(lsh+1,lsh+cnt+1,v[i][1])-lsh;
            v[i][2]=lower_bound(lsh+1,lsh+cnt+1,v[i][2])-lsh;
        }
        int ans=0;
        for(re i=1;i<=m;i++)
        {
            ans=0;
            T.change(1,1,maxx,v[i][1],v[i][2],v[i][0]);
            ans=T.query(1,1,maxx);
            printf("%lld\n",ans);
        }
    	return 0;
    }
    
    

    T2 赛

    思路:这道题我们利用一个多指针的思想,首先先将物品分成四类,AB都喜欢,A喜欢B不喜欢,A不喜欢B喜欢,AB都不喜欢,这样我们将他们存储起来并从大到小排序,然后先假设全部选择AB都喜欢的物品,接着将指针进行移动,我在程序中标记了4个我的出错点,具体实现见代码:

    #include<bits/stdc++.h>
    #define int long long
    #define re register int
    #define ii inline int
    #define iv inline void
    using namespace std;
    const int N=2e5+10;
    const int INF=1e15;
    struct CUN
    {
    	int v;
    	friend bool operator < (CUN a,CUN b)
    	{
    		return a.v<b.v;
    	}
    }cun[N],use1[N],use2[N],use3[N],use4[N];
    bool vis1[N],vis2[N];
    int n,m,k,a,b;
    int cnt1,cnt2,cnt3,cnt4,c1,c2,c3,c4;
    int ans=INF,out;
    ii read()
    {
    	int x=0;
    	bool f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-')
    			f=0;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<3)+(x<<1)+(ch^48);
    		ch=getchar();
    	}
    	return f?x:(-x);
    }
    inline bool pd()
    {
    	if(cnt1>=m&&m<k)
    		return 1;
    	if(cnt1+cnt2<k||cnt1+cnt3<k||k*2>m+cnt1)//3
    		return 1;
    	return 0;
    }
    #undef int
    int main()
    {
    	#define int long long
    	n=read();
    	m=read();
    	k=read();
    	for(re i=1;i<=n;i++)
    		cun[i].v=read();
    	a=read();
    	for(re i=1;i<=a;i++)
    		vis1[read()]=1;
    	b=read();
    	for(re i=1;i<=b;i++)
    		vis2[read()]=1;
    	for(re i=1;i<=n;i++)
    	{
    		if(vis1[i]&&vis2[i])
    			use1[++cnt1].v=cun[i].v;
    		else if(vis1[i])
    			use2[++cnt2].v=cun[i].v;
    		else if(vis2[i])
    			use3[++cnt3].v=cun[i].v;
    		else
    			use4[++cnt4].v=cun[i].v;
    	}
    	if(pd())
    	{
    		printf("-1\n");
    		return 0;
    	}
    	sort(use1+1,use1+cnt1+1);
    	sort(use2+1,use2+cnt2+1);
    	sort(use3+1,use3+cnt3+1);
    	sort(use4+1,use4+cnt4+1);
    	c1=min(cnt1,m);	
    	if(c1<m)//1
        {
            c2=c3=max(0ll,k-cnt1);
            int now=m-c1-c2-c3;
            while(now--)
            {
                if(use2[c2+1]<use3[c3+1]&&use2[c2+1]<use4[c4+1])
                	c2++;
                else if(use3[c3+1]<use2[c2+1]&&use3[c3+1]<use4[c4+1])
                	c3++;
                else 
                	c4++;
            }
        }
    	for(re i=1;i<=c1;i++)
    		out+=use1[i].v;
    	for(re i=1;i<=c2;i++)
    		out+=use2[i].v;
    	for(re i=1;i<=c3;i++)
    		out+=use3[i].v;
    	for(re i=1;i<=c4;i++)
    		out+=use4[i].v;
    	ans=min(ans,out);
    	while(c1)
    	{
    		c1--;
    		out-=use1[c1+1].v;
    		int fl=0;
    		if(c1+c2<k&&c2<cnt2)
    		{
    			++c2;
    			out+=use2[c2].v;
    			++fl;
    		}
    		if(c1+c3<k&&c3<cnt3)
    		{
    			++c3;
    			out+=use3[c3].v;
    			++fl;
    		}
    		if(fl==2)
    		{
    			if(c4==0)
    				break;//2
    			out-=use4[c4].v;
    			--c4;	
    		}
    		else if(!fl)//4
    		{
    			if(use2[c2+1].v<use3[c3+1].v&&use2[c2+1].v<use4[c4+1].v)
    			{
    				++c2;
    				out+=use2[c2].v;
    			}
    			else if(use3[c3+1].v<use2[c2+1].v&&use3[c3+1].v<use4[c4+1].v)
    			{
    				++c3;
    				out+=use3[c3].v;
    			}
    			else
    			{
    				++c4;
    				out+=use4[c4].v;
    			}
    		}
    		ans=min(ans,out);
    	}
    	printf("%lld\n",ans);
    	return 0;
    }
    
    

    T3 题

    思路:

    但是,我们不能暴力枚举每个状态,但是我们可以利用逆向思维反向推出合法的状态,具体实现见代码:

    
    
    #include<bits/stdc++.h>
    #define re register int
    #define ii inline int
    #define iv inline void
    using namespace std;
    const int N=410;
    const int M=5e4+10;
    struct CUN
    {
    	int u,v;
    }use[M];
    int n,m,ans;
    int f[N];
    bitset<N>g[N];
    ii read()
    {
    	int x=0;
    	bool f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-')
    			f=0;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<3)+(x<<1)+(ch^48);
    		ch=getchar();
    	}
    	return f?x:(-x);
    }
    int main()
    {
    	n=read();
    	m=read();
    	for(re i=1;i<=m;i++)
    	{
    		use[i].u=read();
    		use[i].v=read();
    	}
    	for(re i=1;i<=n;i++)
    	{
    		f[i]=1;
    		g[i][i]=1;
    		for(re j=m;j;j--)
    		{
    			int U=use[j].u,V=use[j].v;
    			if(g[i][U]&&g[i][V])
    			{
    				f[i]=0;
    				break;
    			}	
    			if((!g[i][U])&&(!g[i][V]))
    				continue;
    			g[i][U]=1;
    			g[i][V]=1;
    		}
    	}
    	for(re i=1;i<=n;i++)
    	{
    		if(!f[i])
    			continue;
    		for(re j=i+1;j<=n;j++)
    		{
    			if(!f[j])
    				continue;
    			if((g[i]&g[j])!=0)
    				continue;
    			++ans;
    		}
    	}
    	printf("%d\n",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    JS魔法堂:阻止元素被选中
    JS魔法堂之实战:纯前端的图片预览
    CentOS6.5菜鸟之旅:纯转载Linux目录结构
    Vim杂记:Sublime的配色方案
    Vim杂记:markdown插件
    CentOS6.5菜鸟之旅:中文编辑器忍痛放弃Sublime
    JS魔法堂:Data URI Scheme介绍
    CentOS6.5菜鸟之旅:安装ATI显卡驱动
    JS魔法堂:获取当前脚本文件的绝对路径
    腊八蒜
  • 原文地址:https://www.cnblogs.com/WindZR/p/15058786.html
Copyright © 2011-2022 走看看