4 条题解

  • 3
    @ 2026-2-25 10:45:28

    如果按照步骤顺序模拟覆盖关系,会超时。我们不妨从后往前操作,先完成后面的涂色,再完成前面的涂色,后面的涂色直接覆盖前面的涂色。每次涂色时只需要判断会被覆盖掉几格,而不需要模拟整个图形,非常的~优雅~。

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 300005;
    long long row_cnt, col_cnt;/*统计一共涂了几行几列*/
    long long ans[N], t[N], c[N], k[N];/*将涂色操作存储, 逆序执行*/
    map<int, bool> row, col;/*记录每一行是否被涂色过*/
    int main()
    {
        int n, m, C, Q; cin >> m >> n >> C >> Q;
        for (int i = 1; i <= Q; i++)
            cin >> t[i] >> k[i] >> c[i];
            /*提前记录涂色操作, 逆向离线处理, 因为后面的涂色会覆盖前面的涂色*/
        
        for (int i = Q; i; i--)
        {
            if (t[i] == 1 && !row[k[i]])/*如果涂过了就不能覆盖*/
                ans[c[i]] += n - col_cnt/*减去被覆盖掉的*/, row_cnt++/*涂过的行数加一*/, row[k[i]] = 1/*本行被涂过*/;
            if (t[i] == 2 && !col[k[i]])/*如果涂过了就不能覆盖*/
                ans[c[i]] += m - row_cnt, col_cnt++, col[k[i]] = 1;
        }
        for (int i = 1; i <= C; i++)
            cout << ans[i] << " ";
        return 0;
    }
    
    • 1
      @ 2026-2-25 9:29:56

      暴力O(Q*max(H,W))会超时,所以考虑STL辅助解决问题。

      题意标出:用颜色c涂一个格子会将该格子的颜色变为颜色c无论它之前是什么颜色。 所以可以从后向前,省去遍历更新的时间,只需处理这一次涂色能成功涂上哪几个未涂的格子即可。

      同样记得开long long,ans[i]max=(1e92)ans[i]_{max}=(1e9^2)

      #include<bits/stdc++.h>
      using namespace std;
      #define ll long long
      ll h,w,c,q,ans[300010],t[300010],n[300010],c1[300010];
      unordered_map<ll,bool>row,column;
      int main()
      {
      	scanf("%lld%lld%lld%lld",&h,&w,&c,&q);
      	for(int i=1;i<=q;i++)scanf("%lld%lld%lld",&t[i],&n[i],&c1[i]);
      	memset(ans,0ll,sizeof ans);//好习惯 
      	for(int i=q;i;i--)
      	{
      		if(t[i]==1)//涂行 
      		{
      			if(!row[n[i]])ans[c1[i]]+=w,h--;
      			//未涂就涂上,也意味着涂列的时候这一行的那一格不会再被染色,所以h-- 
      			row[n[i]]=1;//标记已涂 
      		}
      		else
      		{
      			if(!column[n[i]])ans[c1[i]]+=h,w--;
      			column[n[i]]=1;//均同上,行列转换而已 
      		}
      	}
      	for(ll i=1;i<=c;i++)printf("%lld ",ans[i]);
      	return 0;
      }
      
      • 0
        @ 2026-2-25 9:59:10
        #include<bits/stdc++.h>
        using namespace std;
        constexpr int N=3e5+10;
        int H,W,C,Q;
        long long t[N],k[N],c[N],ans[N];
        unordered_map<int,bool> mp1,mp2;
        int main(){
        	ios::sync_with_stdio(false);
        	cin.tie(0),cout.tie(0);
        	cin>>H>>W>>C>>Q;
        	for(int i=1;i<=Q;i++)
        		cin>>t[i]>>k[i]>>c[i];
        	//由于是倒叙便利,所以颜色以最先遇到的为准 
        	do{//倒序遍历 
        		//此时H,W表示剩余未涂色过的行和列
        		//mp1和mp2防止重复涂色 
        		if(t[Q]==1&&!mp1[k[Q]]){
        			ans[c[Q]]+=W;//加上剩余未吐过色的列数 
        			mp1[k[Q]]=true;
        			H--;//此行涂色过了 
        		}
        		if(t[Q]==2&&!mp2[k[Q]]){
        			ans[c[Q]]+=H;//加上剩余未吐过色的行数
        			mp2[k[Q]]=true;
        			W--;//该列涂色过了 
        		}
        	}while(Q--);
        	for(int i=1;i<=C;i++)
        		cout<<ans[i]<<" ";
        	return 0;
        }
        
        • 0
          @ 2026-2-25 8:44:44
          #include<bits/stdc++.h>
          using namespace std;
          typedef long long ll;
          int n,m,C,q;
          struct N{
          	int op,x,c;
          }qq[300010];
          unordered_map<int,int> vr,vc;
          ll ans[300010];
          int main(){
          	ios::sync_with_stdio(0);
          	cin.tie(0);
          	cin>>n>>m>>C>>q;
          	for(int i=1;i<=q;i++){
          		cin>>qq[i].op>>qq[i].x>>qq[i].c;
          	}
          	int r=n,c=m;
          	for(int i=q;i>=1;i--){
          		if(qq[i].op==1){
          			if(!vr[qq[i].x])ans[qq[i].c]+=c,r--;
          			vr[qq[i].x]=1;
          		}
          		else{
          			if(!vc[qq[i].x])ans[qq[i].c]+=r,c--;
          			vc[qq[i].x]=1;
          		}
          	}
          	for(int i=1;i<=C;i++){
          		cout<<ans[i]<<" ";
          	}
          	return 0;
          }
          
          
          • 1

          信息

          ID
          2516
          时间
          2000ms
          内存
          1024MiB
          难度
          6
          标签
          递交数
          37
          已通过
          11
          上传者