zoukankan      html  css  js  c++  java
  • 「USACO 2021 US Open Platinum」United Cows of Farmer John

    「USACO 2021 US Open Platinum」United Cows of Farmer John

    考虑依次枚举右端点(i),计算左边合法的方案数,设一个数(x)上次出现的位置为(lst_x)

    (i)能够作为右端点的区间就是([lst_{a_i}+1,i-2])

    考虑什么样的位置可以作为左端点,显然这个点在([1,i])中是最后一次出现

    我们将不妨这样的点权值设为(w_i=1)

    考虑一个点作为中间点贡献怎样的区间,同样的,这个点在([1,i])中是最后一次出现

    并且,能够贡献的区间(>)上一次出现的位置(lst_x)

    这个中间点能够匹配的左端点个数就是(displaystyle sum_{k=lst_{a_j}+1}^{j-1} w_k)

    现在我们要用数据结构动态修改某一个位置的(w_i),增减([lst_{a_j}+1,j-1])的区间,查询([lst_{a_i}+1,i-2])

    不妨再为一个点增加点权(t_i),此时我们要维护的操作

    1.单点修改(w_i)

    2.区间修改(t_i)

    3.求(w_it_i)区间和

    在线段树上每个节点维护(w_i)之和,(w_it_i)之和,可以标记永久化(t_i)

    具体实现参考代码(实际写得很丑)

    const int N=2e5+10,INF=1e9+10;
    
    
    int n;
    int lst[N],lst2[N],cnt;
    ll s1[N<<2],s2[N<<2];
    int t[N<<2];
    // s1表示w之和,s2表示区间内部t[i]*w[i]之和,t[i]现在是永久化的标记
    void Up(int p){
    	s2[p]=s2[p<<1]+s2[p<<1|1];
    	s1[p]=s1[p<<1]+s1[p<<1|1]+s2[p]*t[p];
    }
    void Upd(int p,int l,int r,int x){
    	if(l==r) {
    		s2[p]^=1,s1[p]=t[p]*s2[p];
    		return;
    	}
    	int mid=(l+r)>>1;
    	x<=mid?Upd(p<<1,l,mid,x):Upd(p<<1|1,mid+1,r,x);
    	Up(p);
    }
    
    void Upd(int p,int l,int r,int ql,int qr,int x){
    	if(ql>qr) return;
    	if(ql<=l && r<=qr) {
    		t[p]+=x,s1[p]+=x*s2[p];
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(ql<=mid) Upd(p<<1,l,mid,ql,qr,x);
    	if(qr>mid) Upd(p<<1|1,mid+1,r,ql,qr,x);
    	Up(p);
    }
    
    struct Node{
    	ll x,y;
    	Node(ll x=0,ll y=0):x(x),y(y){  }
    	Node operator + (const Node __) { return Node(x+__.x,y+__.y); }
    };
    Node Que(int p,int l,int r,int ql,int qr){
    	if(ql>qr) return Node();
    	if(ql<=l && r<=qr) return Node(s1[p],s2[p]);
    	int mid=(l+r)>>1; Node res;
    	if(ql<=mid) res=res+Que(p<<1,l,mid,ql,qr);
    	if(qr>mid) res=res+Que(p<<1|1,mid+1,r,ql,qr);
    	res.x+=res.y*t[p];
    	return res;
    }
    
    int main(){
    	n=rd();
    	ll ans=0;
    	rep(i,1,n) {
    		int x=rd();
    		if(lst[x]) {
    			Upd(1,1,n,lst[x]),cnt--;
    			Upd(1,1,n,lst2[x]+1,lst[x],-1);
    		}
    		Node t=Que(1,1,n,lst[x]+1,i-2);
    		ans+=t.x;
    		Upd(1,1,n,i),cnt++,Upd(1,1,n,lst[x]+1,i-1,1);
    		lst2[x]=lst[x],lst[x]=i;
    	}
    	printf("%lld
    ",ans);
    }
    
  • 相关阅读:
    解决HTML乱码
    <img> 标签的 src 属性
    tomcat 启动报错 解决办法 A child container failed during&nbsp
    SpringMVC拦截器(资源和权限管理)
    Java实现文件上传-按钮弹出上传页面
    Socket规划中的局域网内测试
    iOS pragma mark要使用
    dwz 照片回头处理
    图像显示和逐渐消失
    讲座:采用Store检查邮件(1)
  • 原文地址:https://www.cnblogs.com/chasedeath/p/14764083.html
Copyright © 2011-2022 走看看