首页 > 其他分享 >CF1980F1 & F2 Field Division

CF1980F1 & F2 Field Division

时间:2024-08-29 22:07:12浏览次数:9  
标签:F2 pu int long 贡献 Field ans CF1980F1 id

前言

纪念一下独立做出来的 \(2400\) 的题

Easy version

思路

先说 \(Easy\) 版本的

我们走路的方式只有可能是这种样子:

(出处:luogu user FiraCode)
不想手绘图了

即对列排序后,所形成的一个行编号上升的序列

所以 \(Easy\) 就很简单了,对于每一列的最大值,如果大于当前前缀最大值,则它就有贡献

但是如何求 如果鲍勃没有给爱丽丝任何喷泉,那么爱丽丝可以拥有的地块的最大面积 呢?

观察每两个有贡献的点之间的差别,发现其实就是这两个点围成的矩阵及其下方的整个区域

形象化地说,设 \(lx\) 为左边点的行编号,\(ly\) 为左边点的列坐标,\(ry\) 为右边点的列坐标

则贡献为 \([n-(lx+1)+1] \times (ry-ly)\) (可以结合样例给的图理解)

注意最后一个有贡献的点后面的列的贡献需要在最后加一下

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
struct node
{
    int x,y;
    int id;
    bool operator <(const node &o)const
    {
        if(y==o.y) return x<o.x;
        return y<o.y;
    }
}a[N];
int mx[N];
int ans[N];
signed main()
{
    int _;
    cin>>_;
    while(_--)
    {
        int n,m,k;
        cin>>n>>m>>k;
        for(int i=1;i<=k;i++)
        {
            scanf("%lld%lld",&a[i].x,&a[i].y);
            a[i].id=i;
            ans[i]=0;
        }
        sort(a+1,a+1+k);
        
        for(int i=1;i<=k;i++) mx[i]=max(mx[i-1],a[i].x);
        int w=1;
        a[0].y=1;
        long long pu=0;
        int l=1;
        int r=1; 
        for(int i=1;i<=k;i++)
        {
            int j=i;
            while(j<=k&&a[j].y==a[i].y) j++;
        
            if(a[j-1].x>mx[i-1])
            {
                ans[a[j-1].id]=1;
                pu+=(n-l+1)*(a[i].y-r);
                r=a[i].y;
                l=a[j-1].x+1;
            } 
            
            i=j-1;
        }
        pu+=(m-r+1)*(n-l+1);
        printf("%lld\n",pu);
        for(int i=1;i<=k;i++) printf("%lld ",ans[i]);
        puts("");
    }
}

hard version

思路

首先,请确保你已经阅读了 \(Easy\) 版本

然后困难版本让你求如果可以包含当前温泉,问会增加多少贡献

一个重要性质,对于当前贡献点的下一个贡献点,如果去掉了当前贡献点,则下一个贡献点及其后面产生的贡献是不变的

所以对于中间的区域,直接暴力更新即可,因为每个温泉只会被遍历 \(1\) 次,所以复杂度 \(O(n)\)

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
struct node
{
    int x,y;
    int id;
    bool operator <(const node &o)const
    {
        if(y==o.y) return x<o.x;
        return y<o.y;
    }
}a[N];
int mx[N];
int ans[N];
int id[N];
int sum[N];
signed main()
{
    int _;
    cin>>_;
    while(_--)
    {
        int n,m,k;
        cin>>n>>m>>k;
		for(int i=0;i<=k+5;i++)
        {
        	a[i]={0,0,0};
        	ans[i]=0;
            id[i]=0;
            mx[i]=0;
            sum[i]=0;
		}
        for(int i=1;i<=k;i++)
        {
            scanf("%lld%lld",&a[i].x,&a[i].y);
            a[i].id=i;
            
        }
        
		a[k+1]={0,0,0};
        sort(a+1,a+1+k);
        
        for(int i=1;i<=k;i++)
        {
            if(a[i].x>mx[i-1])
            {
                mx[i]=a[i].x;
                id[i]=i;
            }
            else
            {
                mx[i]=mx[i-1];
                id[i]=id[i-1];
            }
        }
        int w=1;
        a[0].y=1;
        long long pu=0;
        int l=1;
        int r=1; 
        for(int i=1;i<=k;i++)
        {
            int j=i;
            while(j<=k&&a[j].y==a[i].y) j++;
        
            if(a[j-1].x>mx[i-1])
            {
				ans[a[j-1].id]=1;
                
                pu+=(n-l+1)*(a[i].y-r);
                sum[j-1]=pu;
                r=a[i].y;
                l+=a[j-1].x-mx[i-1];
            } 
            
            i=j-1;
        }
        pu+=(m-r+1)*(n-l+1);
        r=1;
        l=1;
        int pre=0;
        for(int i=1;i<=k;i++)
        {
            if(!ans[a[i].id]) continue;
            ans[a[i].id]=sum[pre];
			int mxx=l-1;
            if(a[i-1].y==a[i].y&&a[i-1].x>mxx)
            {
                ans[a[i].id]+=(n-l+1)*(a[i-1].y-r);
                mxx=a[i-1].x; 
                l=a[i-1].x+1;
                r=a[i-1].y;
                pre=i-1;
            }
            int f=0;
            
            for(int j=i+1;j<=k;j++)
            {
            	if(a[j+1].y==a[j].y) continue;
		if(a[j].x>mxx)
                {
                    ans[a[i].id]+=(n-l+1)*(a[j].y-r);
                    r=a[j].y;
                    l=a[j].x+1;
                    mxx=a[j].x;
                }
                if(ans[a[j].id]==1)
                {
                    ans[a[i].id]=ans[a[i].id]-sum[j];
                    f=1;
                    break;
                }
                
            }
            if(f==0)
            {
            	ans[a[i].id]+=(m-r+1)*(n-l+1);
            	ans[a[i].id]-=pu;
                if(ans[a[i].id]<0) ans[a[i].id]=n;
	    }
            r=a[i].y;
            l=a[i].x+1;
            pre=i;
        }
        
        printf("%lld\n",pu);
        for(int i=1;i<=k;i++) printf("%lld ",ans[i]);
        puts("");
    }
}

标签:F2,pu,int,long,贡献,Field,ans,CF1980F1,id
From: https://www.cnblogs.com/Oistream/p/18387608

相关文章

  • AWTF2024A Moving Slimes 题解
    发现史莱姆不合并也不会影响答案,所以就不用考虑合并了。这样处理之后,史莱姆的移动可以看作是受到与其不在同一位置的史莱姆的吸引所完成的,每只史莱姆可以给其他史莱姆一个单位的吸引力。因为每只史莱姆提供的吸引力是恒定的,所以考虑把吸引力放在它们的重心上,设\(pre_i\)表示坐......
  • BaseCTF2024-week2-Crypto部分题目wp
    先放一下官方的wp(我这里只放我出的题):https://j0zr0js7k7j.feishu.cn/wiki/JQbiwKdvtiR49VkMj5RcmPvPn7crandom_primesfromCrypto.Util.numberimport*importrandomdefgen_n():primes=[getPrime(128)for_inrange(256)]n=1foriinrange(100):......
  • 网站提示431 Request Header Fields Too Large:请求头字段太大怎么办
    当遇到“431RequestHeaderFieldsTooLarge”错误时,这意味着客户端发送的请求头中的一个或多个字段超过了服务器允许的最大长度。这种情况通常发生在请求头中的某个字段(如Cookie或Authorization)过长时。解决方案检查请求头确认请求头中的字段是否过长。特别注意Cook......
  • CF2003E解题报告
    题目描述(来自谷歌翻译)Turtle为您提供\(m\)个区间\([l_1,r_1],[l_2,r_2],\ldots,[l_m,r_m]\)。他认为,如果每个区间(\(l_i\lek_i<r_i\))都存在一个整数\(k_i\),则排列\(p\)是有趣的,并且如果他让从\(1\)到\(m\)的每个整数\(i\)都存在\(a_i=\max\limi......
  • CF2003F 解题报告
    题目描述现在有三个长度为\(n\)的序列\(a,b,c\)。你需要提取一个子序列\(p_1,p_2,\dots,p_m\),满足如下条件:\(\foralli\in(1,m],p_i>p_{i-1}\)。\(\foralli\in(1,m],a_i\geqa_{i-1}\)。\(b_{p_1},b_{p_2},\dots,b_{p_m}\)是互不相同的。在此基础上最大化......
  • 题解:CF235C Cyclical Quest
    题意给定一个主串\(S\)和\(n\)个询问串,求每个询问串的所有循环同构在主串中出现的次数总和。分析后缀自动机好题。循环同构的过程可以看作从该串的头部删除一个字符,并在尾部加入一个字符。在后缀自动机上,跳parent树的过程就相当于删除头部的若干个字符。所以我们可......
  • BaseCTF2024-week1-Crypto部分题目wp
    先放一下官方的wp(我这里只放我出的题):Docs(feishu.cn)babypackfromCrypto.Util.numberimport*importrandomflag=b'BaseCTF{}'m=bytes_to_long(flag)bin_m=bin(m)[2:]length=len(bin_m)a=[1]sum=1foriinrange(length-1):temp=random.randint(2*sum+1,4*su......
  • CF241B Friends 题解
    是异或粽子的超级加强版,但是本题因为\(m\)很大,不能套用那一题的解法。换一种思路:考虑把\(a_i\)从高位到低位插入0-1Trie之后,二分第\(m\)大,通过第\(m\)大求答案。对于二分的一个值\(x\),枚举每个位置\(i\),在0-1Trie上找与\(a_i\)异或值大于等于\(x\)的值的......
  • CF1326F2 Wise Men (Hard Version) 题解
    题目链接点击打开链接题目解法挺难的。可能一步一步推下来也没那么复杂(?基本copytzc_wk的题解/bx肯定不能像\(F1\)用普通的状压求,一个技巧是容斥考虑令\(f_S\)表示\(S\)中为\(1\)的位置\(p_i\)和\(p_{i+1}\)必须认识,为\(0\)的位置随便\(f\)数组相当于答案......
  • diff.js+diff2html-ui.js 使用实例
    <!DOCTYPEhtml><htmllang="zh"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>文件差异对比</title>&......