zoukankan      html  css  js  c++  java
  • codeforce1000C 求线段覆盖次数特殊操作及其拓展

    通过标记起点,使其+1,标记终点后第一个的点,使其-1,然后从头到尾遍历一次,进行类似于前缀和的运算,每次取点的值,当前值为n,表示被n条线段覆盖的区域增加一个

    图解示例:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<stack>
    #include<map>
    #include<vector>
    #include<queue>
    #include<set>
    #include<iomanip>
    #include<cctype> 
    using namespace std;
    const int MAXN=2e5+5;
    const int INF=1<<30;
    const long long mod=1e9+7;
    const double eps=1e-8;
    #define ll long long
    #define edl putchar('
    ')
    #define sscc ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    #define FOR(i,a,b) for(int i=a;i<=b;i++)
    #define ROF(i,a,b) for(int i=a;i>=b;i--)
    #define FORLL(i,a,b) for(ll i=a;i<=b;i++)
    #define ROFLL(i,a,b) for(ll i=a;i>=b;i--)
    #define mst(a) memset(a,0,sizeof(a))
    #define mstn(a,n) memset(a,n,sizeof(a))
    #define zero(x)(((x)>0?(x):-(x))<eps) 
    int n,cnt;
    ll ans[MAXN],las;
    struct num
    {
    	ll l,r;
    }a[MAXN];
    map<ll,int> mp;
    int main()
    {
    	scanf("%d",&n);
    	FOR(i,1,n)
    	scanf("%lld%lld",&a[i].l,&a[i].r);
    	FOR(i,1,n)
    	{
    		mp[a[i].l]++,mp[a[i].r+1]--;
    	}
    	map<ll,int>::iterator it;
    	for(it=mp.begin();it!=mp.end();it++)
    	{
    		if(it==mp.begin())
    		{
    			las=it->first;
    			cnt=0;
    		}
    		ans[cnt]+=it->first-las;
    		cnt+=it->second;
    		las=it->first;
    	}
    	FOR(i,1,n)
    	printf("%lld%c",ans[i],i==n?'
    ':' ');
    }
    

      

    这样的一个思想可以拓展,用于解决一些类似的区间覆盖问题。

     

    拓展一:

    区间染色问题,很简单,再增加一个数组记录颜色即可。

     

    拓展二:

    二维区间(平面覆盖)

    如果把这道题的问题规模扩充到一个平面,要如何处理?

    直接得出一个不同规模的解有些难度,让我们先从已有结论出发:

    标记一个n*m的区间相当于标记长度为m的区间n次,这样一次操作的复杂度是O(n)或O(m)而不是O(1)

    示例:

    我们这样标记就一定要先从左向右处理,然后才能换行,因为这种做法的本质是把平面降成了线,所以要遵循一维的规则(红色区域为覆盖域)。

     注意到一维的规则里,只有上一次的状态(左侧)会对现在的结果产生影响

    因此猜测二维情况下同时与左侧与上侧相关:

    1.处于左边界时,左侧无关联,所以上侧的值要计入当前

    2.处于上边界时,上侧无关联,所以左侧的值要计入当前

    3.处于非边界时,如果同时计入左侧和上侧,会导致值比预期的要大,但如果同时存在上侧和左侧,则左上侧一定存在,减去左上侧的值,那么计数即符合预期。

    得出类似前缀和的算式:(aij)+=(ai-1j)+(aij-1)-(ai-1j-1)

    通过对算式的推演,发现正确的赋值方式如下:

    及其计算的结果:

    符合预期情况。

    牛客网暑期ACM多校训练营(第二场)J题可以用该方法解决

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<stack>
    #include<map>
    #include<vector>
    #include<queue>
    #include<set>
    #include<iomanip>
    #include<cctype> 
    #include<stack>
    #include<ctime>
    using namespace std;
    const int MAXN=1e6+5;
    const int INF=1<<30;
    const long long mod=1e9+7;
    const double eps=1e-8;
    typedef long long ll;
    #define edl putchar('
    ')
    #define sscc ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    #define FOR(i,a,b) for(int i=a;i<=b;i++)
    #define ROF(i,a,b) for(int i=a;i>=b;i--)
    #define FORLL(i,a,b) for(ll i=a;i<=b;i++)
    #define ROFLL(i,a,b) for(ll i=a;i>=b;i--)
    #define mst(a) memset(a,0,sizeof(a))
    #define mstn(a,n) memset(a,n,sizeof(a))
    #define zero(x)(((x)>0?(x):-(x))<eps)
    vector<ll> color[MAXN];
    vector<int> now[MAXN],mp[MAXN];
    int main()
    {
    	int n,m,k,ans;
    	while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    	{
    		ans=0;
    		FOR(i,0,n+1)
    		{
                mp[i].resize(m+5);
                now[i].resize(m+5);
                color[i].resize(m+5);
            }
    		FOR(i,1,n)
    		FOR(j,1,m)
    		{
    			scanf("%d",&mp[i][j]);
    			color[i][j]=0;
    			now[i][j]=0;
    		}
    		int x1,y1,x2,y2;
    		ll t;
    		while(k--)
    		{
    			scanf("%d%d%d%d%lld",&x1,&y1,&x2,&y2,&t);
    			color[x1][y1]+=t;
    			color[x1][y2+1]-=t;
    			color[x2+1][y1]-=t;
    			color[x2+1][y2+1]+=t;
    			
    			now[x1][y1]++;
    			now[x1][y2+1]--;
    			now[x2+1][y1]--;
    			now[x2+1][y2+1]++;
    		}
    		FOR(i,1,n)
    		{
    			FOR(j,1,m)
    			{
    				now[i][j]+=now[i-1][j]+now[i][j-1]-now[i-1][j-1];
    				color[i][j]+=color[i-1][j]+color[i][j-1]-color[i-1][j-1];
    				if(now[i][j]>1) ans++;
    				if(now[i][j]==1&&color[i][j]!=mp[i][j])ans++;
    			}
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

      

    再扩展到三维空间:aijk+=(ai-1jk)+(aij-1k)+(aijk-1)-(ai-1j-1k)-(ai-1jk-1)-(aij-1k-1)+(ai-1j-1k-1)

    赋值ax1y1z1=1,a(x2+1)(y2+1)(z2+1)=1,a其余顶点为-1

  • 相关阅读:
    严重: Parse error in application web.xml file at jndi:/localhost/ipws/WEBINF/web.xml java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml
    Failed to install .apk on device 'emulator5554': timeout解决方法
    java.lang.NoClassDefFoundError:org.jsoup.Jsoup
    Conversion to Dalvik format failed: Unable to execute dex:解决方法
    apache Digest: generating secret for digest authentication ...
    Description Resource Path Location Type Project has no default.properties file! Edit the project properties to set one.
    android service随机自启动
    MVC3 安装部署
    EF 4.3 CodeBased 数据迁移演练
    SQL Server 2008开启sa账户
  • 原文地址:https://www.cnblogs.com/qq936584671/p/9306178.html
Copyright © 2011-2022 走看看