zoukankan      html  css  js  c++  java
  • 【洛谷6105】[Ynoi2010] y-fast trie(set)

    点此看题面

    大致题意: 给定一个集合(S),支持两种操作:加入一个数、删除一个数。每次操作后输出(max_{iin S,jin S,i ot=j}((i+j)\%C))。(强制在线)

    分类

    首先,第一步显然是对于读入的每个(x)将它向(C)取模,保证(0le x<C)

    要注意一点,原题中保证没有重复元素,但在我们这么一处理之后就可能会重复,我一开始就因为这个原因挂了。

    既然已经满足(0le x<C)了,则((i+j)\%C)无非有两种可能:

    • ((i+j)\%C=i+j-C):显然求出当前的最大值和次大值作为(i,j)即可。
    • ((i+j)\%C=i+j),这个比较麻烦,是我们接下来着重讨论的。

    最优匹配

    我们定义(i)的最优匹配为(max_{jin S,i+j<C}j)

    不难发现,必然存在至少一对数满足它们互为最优匹配,且最优解必然是某一对互为最优匹配的数。

    对于每一对互为最优匹配的(i,j),我们可以把(i+j)扔入一个(set)中存储。(注意,这里的(set)(multiset),为了叙述方便,简称为(set)


    加入一个数(x),我们需要找到它的最优匹配(y),接着找到(y)原先的最优匹配(z)

    如果(xle z),那么(y)的最优匹配显然还是(z),不予操作。

    否则,如果(z)的最优匹配是(y),那么我们需要在(set)中删去(y+z)

    然后,由于(x,y)互为最优匹配,我们再把(x+y)扔入(set)中。


    删除一个数(x),也是类似地找出最优匹配(y)和删去(x)(y)的最优匹配(z)

    如果(xle z),说明(y)的最优匹配原本就是(z),删除(x)没有任何影响,不予操作。

    否则,如果(z)的最优匹配时(y),那么我们需要在(set)中加入(y+z)

    然后,由于(x,y)原本互为最优匹配,删去(x)之后这对最优匹配就不存在了,因此在(set)中删去。


    还有一个遗留问题,如何找到一个数的最优匹配?

    我们只要另开一个(multiset),存下所有的元素,然后只要求最大的小于等于(C-x-1)就可以了。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 500000
    using namespace std;
    int tot,X;multiset<int> V,S;multiset<int>::iterator it;
    class FastIO
    {
    	private:
    		#define FS 100000
    		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
    		#define pc(c) (C==E&&(clear(),0),*C++=c)
    		#define D isdigit(c=tc())
    		int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
    	public:
    		I FastIO() {A=B=FI,C=FO,E=FO+FS;}
    		Tp I void read(Ty& x) {x=0;W(!D);W(x=(x<<3)+(x<<1)+(c&15),D);}
    		Tp I void writeln(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);pc('
    ');}
    		I void IEE() {pc('E'),pc('E'),pc('
    ');}
    		I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
    }F;
    I int Match(CI x,bool f)//求最优匹配,f表示是否要除去x自身
    {
    	if(!~x) return -1;if((it=V.upper_bound(X-x-1))==V.begin()) return -1;//找不到返回-1
    	if(--it,f&&*it==x&&V.count(x)==1) return it==V.begin()?-1:*--it;return *it;//特判等于自身的情况
    }
    I void Ins(CI x)//插入
    {
    	RI y,z;if(tot==1) goto End;y=Match(x,0),z=Match(y,1);
    	~y&&x>=z&&(~z&&y==Match(z,1)&&(S.erase(S.find(y+z)),0),S.insert(x+y),0);End:V.insert(x);
    }
    I void Del(CI x)//删除
    {
    	if(V.erase(V.find(x)),!tot) return;RI y=Match(x,0),z=Match(y,1);
    	~y&&x>=z&&(~z&&y==Match(z,1)&&(S.insert(y+z),0),S.erase(S.find(x+y)),0);
    }
    I int QV() {return V.count(*(it=--V.end()))>1?(*it<<1)%X:(*it+*--it)%X;}//(i+j)%C=i+j-C
    I int QS() {return S.empty()?-1:*--S.end();}//(i+j)%C=i+j
    int main()
    {
    	RI Qt,op,x,lst=0;F.read(Qt),F.read(X);W(Qt--)
    		F.read(op),F.read(x),x^=lst,op==1?(++tot,Ins(x%X)):(--tot,Del(x%X)),//tot记录元素个数
    		tot<2?(lst=0,F.IEE()):F.writeln(lst=max(QV(),QS()));//tot<2输出EE,否则询问
    	return F.clear(),0;
    }
    
  • 相关阅读:
    SPOJ913 Query on a tree II
    SPOJ375 Query on a tree
    HDU4348 To the moon
    Bzoj2753 [SCOI2012]滑雪与时间胶囊
    HDU4612 Warm up
    Uva11374 Airport Express
    Uva1624 Knots
    DevExpress的GridControl的使用以及怎样添加列和绑定数据源
    C#中使用Path、Directory、Split、Substring实现对文件路径和文件名的常用操作实例
    ZedGraph的曲线的LineItem对象的Tag属性存储信息进而在鼠标悬浮时进行显示
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu6105.html
Copyright © 2011-2022 走看看