[WC2016]鏖战表达式

鏖(áo)战

第一次做这种实现接口的交互题!感觉还挺好玩的

朴素的思想就是先找到当前最低优先级的运算符,把式子分成几部分递归计算,因为有交换律和结合律所以同优先级乱算就可以了

优先级这个东西好像在treap里也有?

所以我们可以用fhqtreap维护整个式子,运算符的优先级原封不动,因为数值一定要是叶子节点所以数值的优先级为$+\infty$

为了保证treap不会退化,在merge($x$,$y$)时如果$fix_x=fix_y$那么就按(以$x$为根的概率和以$y$为根的概率之比为$\dfrac{siz_x}{siz_y}$)来合并

需要可持久化,pushdown时要复制两个节点,修改时也要复制节点

因为有维护标记,所以merge时以哪个点为根就复制再pushdown哪个点,split时先复制然后pushdown,两种操作都要在最后pushup

运行的时候新建一个文件,在这个文件上编译调试即可

#include"expr.cpp"
#include"grader.cpp"

我是不是太智障了...自己写swap没加引用符号调了一晚上调不出来

第一次交90,后面两个点调用F的次数超限,去看了一下栋爷的博客,发现初始化时反着merge就可以A,不知道是什么原理w求解释

#include<stdio.h>
#include<stdlib.h>
#include"expr.h"
#define maxn 30000010
int rt[20010],l[maxn],r[maxn],rv[maxn],siz[maxn],fix[maxn],tot,M;
Data s[maxn];
bool cmp(int x,int y){
	if(fix[x]==fix[y])return rand()%(siz[x]+siz[y])<siz[x];
	return fix[x]<fix[y];
}
void pushup(int x){
	siz[x]=siz[l[x]]+siz[r[x]]+1;
	if(fix[x]<101&&l[x]!=0&&r[x]!=0)s[x]=F(s[l[x]],s[r[x]],fix[x]);
}
int node(int u){
	tot++;
	int&x=tot;
	l[x]=l[u];
	r[x]=r[u];
	siz[x]=siz[u];
	rv[x]=rv[u];
	fix[x]=fix[u];
	s[x]=s[u];
	return x;
}
void swap(int&a,int&b){a^=b^=a^=b;}
void gao(int&u){
	int x=node(u);
	rv[x]^=1;
	swap(l[x],r[x]);
	u=x;
}
void pushdown(int x){
	if(rv[x]){
		if(l[x])gao(l[x]);
		if(r[x])gao(r[x]);
		rv[x]=0;
	}
}
struct pair{
	int l,r;
	pair(int a=0,int b=0){l=a;r=b;}
};
pair split(int x,int k){
	if(x==0)return pair();
	int u=node(x);
	pushdown(u);
	pair s;
	if(k<=siz[l[u]]){
		s=split(l[u],k);
		l[u]=s.r;
		s.r=u;
	}else{
		s=split(r[u],k-siz[l[u]]-1);
		r[u]=s.l;
		s.l=u;
	}
	pushup(u);
	return s;
}
int merge(int x,int y){
	if(x==0&&y==0)return 0;
	if(x==0)return node(y);
	if(y==0)return node(x);
	int u;
	if(cmp(x,y)){
		u=node(x);
		pushdown(u);
		r[u]=merge(r[u],y);
	}else{
		u=node(y);
		pushdown(u);
		l[u]=merge(x,l[u]);
	}
	pushup(u);
	return u;
}
void init(int test_id,int n,int m,int k,const Data*a,const int*ops){
	srand(19260817);
	int i;
	rt[0]=1;
	siz[1]=1;
	fix[1]=101;
	s[1]=a[n-1];
	tot=1;
	for(i=n-1;i>0;i--){
		tot++;
		siz[tot]=2;
		fix[tot]=ops[i];
		tot++;
		siz[tot]=1;
		fix[tot]=101;
		s[tot]=a[i-1];
		l[tot-1]=tot;
		rt[0]=merge(tot-1,rt[0]);
	}
}
Data modify_data(int id,int pos,Data x){
	pair a,b;
	int u;
	a=split(rt[id],pos<<1);
	b=split(a.r,1);
	u=node(b.l);
	s[u]=x;
	M++;
	rt[M]=merge(a.l,merge(u,b.r));
	return s[rt[M]];
}
Data modify_op(int id,int pos,int new_op){
	pair a,b;
	int u;
	a=split(rt[id],(pos<<1)-1);
	b=split(a.r,1);
	u=node(b.l);
	fix[u]=new_op;
	M++;
	rt[M]=merge(a.l,merge(u,b.r));
	return s[rt[M]];
}
Data reverse(int id,int l,int r){
	pair a,b;
	a=split(rt[id],l<<1);
	b=split(a.r,(r-l)<<1|1);
	gao(b.l);
	M++;
	rt[M]=merge(a.l,merge(b.l,b.r));
	return s[rt[M]];
}

原文地址:https://www.cnblogs.com/jefflyy/p/8203741.html

时间: 2025-01-13 08:30:23

[WC2016]鏖战表达式的相关文章

转:鏖战双十一-阿里直播平台面临的技术挑战(webSocket, 敏感词过滤等很不错)

转自:http://www.infoq.com/cn/articles/alibaba-broadcast-platform-technology-challenges 鏖战双十一-阿里直播平台面临的技术挑战 作者 陈康贤 发布于 2016年1月28日 | 2 讨论 分享到:微博微信FacebookTwitter有道云笔记邮件分享 稍后阅读 我的阅读清单 前言:一直以来双十一都是以交易为重心,今年当然也是如此,但是这并不妨碍万能的淘宝将双十一打造的让用户更欢乐.体验更丰富.玩法更多样.内容更有趣

.NET深入解析LINQ框架(六:LINQ执行表达式)

阅读目录: 1.LINQ执行表达式 在看本篇文章之前我假设您已经具备我之前分析的一些原理知识,因为这章所要讲的内容是建立在之前的一系列知识点之上的,为了保证您的阅读顺利建议您先阅读本人的LINQ系列文章的前几篇或者您已经具备比较深入的LINQ原理知识体系,防止耽误您的宝贵时间. 到目前为止我们对LINQ的执行原理已经很清楚了,从它的前期构想到它真正为我们所用都有足够的证据,但是似乎问题并没有我们想的那么简单,问题总是在我们使用中频频出现尤其是新技术的使用,当然有问题才能有进步. 一:LINQ执行

Lambda表达式实战视频教程

视频教程地址: https://my.oschina.net/u/3217554/blog/1507456 1:Lambda表达式及函数式接口介绍 2:Lambda表达式详解 3:方法的引用(一) 4:方法的引用(二) 5:Stream API(一) 6:Stream API(二) 7:Lambda表达式.方法的引用.Stream API实战

lambda表达式封装对数据库的查询

前言: 1.为什么要封装lambda表达式数据库查询,原因有一下几点: 1.1.在以往的开发中进行数据库表查询时,其实所需要的字段就是其中几个,但是在开发中,开发者往往习惯select * 进行查询,当数据多和用户量多时,查询的效率会降低. 1.2.在写查询where条件的时候,总是用string.format去拼接字符串,开发效率低. 1.3.代码不够优雅,代码中嵌套和多sql语句,如果是表字段发生改变时编译器检查不出来,代码出错的概率大. 1.4.本着 write less  do more

坑爹的EL 表达式。

先说结论: Property 'OrgName0' not found on type EL表达式只与相关类的get方法的有关,就算你没定义变量,get 方法直接返回一个变量,或者常量都可以.这条没问题. EL表达式的大小写规则:当get方法后的字符如果前两个都是大写时,EL表达式需要大写.除此之外均为小写. package com.dobs.codedeploy.domain; public class Image { private String imageName;private Stri

Spring AOP中pointcut expression表达式解析 及匹配多个条件

Pointcut 是指那些方法需要被执行"AOP",是由"Pointcut Expression"来描述的. Pointcut可以有下列方式来定义或者通过&& || 和!的方式进行组合. args() @args() execution() this() target() @target() within() @within() @annotation 其中 execution 是用的最多的,其格式为: execution(modifiers-pat

Lambda表达式

import org.junit.Test; import java.util.Comparator; import java.util.function.Consumer; /** * 一.Lambda 表达式基础语法:Java8中引入一个新的操作符"->"该操作符称为箭头操作符或Lambda操作符 * 箭头操作符将Lambda表达式拆分为两部分: * 左侧: Lambda表达式的参数列表 * 右侧: Lambda表达式中所需要执行的功能,即Lambda体 * * 语法格式一:

算法训练 表达式计算

问题描述 输入一个只包含加减乖除和括号的合法表达式,求表达式的值.其中除表示整除. 输入格式 输入一行,包含一个表达式. 输出格式 输出这个表达式的值. 样例输入 1-2+3*(4-5) 样例输出 -4 数据规模和约定 表达式长度不超过100,表达式运算合法且运算过程都在int内进行. import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.uti

JAVAWEB开发之Session的追踪创建和销毁、JSP详解(指令,标签,内置对象,动作即转发和包含)、JavaBean及内省技术以及EL表达式获取内容的使用

Session的追踪技术 已知Session是利用cookie机制的服务器端技术,当客户端第一次访问资源时 如果调用request.getSession() 就会在服务器端创建一个由浏览器独享的session空间,并分配一个唯一且名称为JSESSIONID的cookie发送到浏览器端,如果浏览器没有禁用cookie的话,当浏览器再次访问项目中的Servlet程序时会将JSESSIONID带着,这时JSESSIONID就像唯一的一把钥匙  开启服务器端对应的session空间,进而获取到sessi