zoukankan      html  css  js  c++  java
  • CF85D Sum of Medians

    CF85D Sum of Medians

    题意翻译

    一个集合,初始为空。现有三个操作:

    1.add:向集合里加入数x,保证加入前集合中没有数x;

    2.del:从集合中删除数x,保证删除前集合中有x;

    3.sum:询问将集合里的数从小到大排序后,求下标i模5余3的数的和。

    现有n次操作,对于每个查询操作,输出答案


    题解Here!

    一开始感觉好不可做啊。。。

    然后发现,线段树好像可以搞一搞。

    线段树每个节点维护$5$个值,即区间中所有$ ext{下标}mod5$后结果相同的位置的值的和。

    即:在区间$[l,r]$上维护:

    $$sum_{i=l}^rv_i[imod 5==0],sum_{i=l}^rv_i[imod 5==1],sum_{i=l}^rv_i[imod 5==2],sum_{i=l}^rv_i[imod 5==3],sum_{i=l}^rv_i[imod 5==4]$$

    再维护区间中有多少个值$num$。

    合并的时候左子树不动,右子树中所有$ ext{下标}mod5==x$的位置应该是$((i-num)\%5+5)\%5$。

    至于线段树怎么动态加点。。。

    其实离线一下就可以把线段树搞成静态,然后离散化一下就好。

    记得开$long long$。

    还与就是在$CF$上是不能用$\%lld$来读入、输出$long long$,所以还是老老实实用$cin,cout$。。。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define LSON rt<<1
    #define RSON rt<<1|1
    #define DATA(x,k) a[x].data[k]
    #define NUM(x) a[x].num
    #define LSIDE(x) a[x].l
    #define RSIDE(x) a[x].r
    #define MAXN 100010
    using namespace std;
    int n,m=0;
    int lsh[MAXN];
    struct Question{
    	int f,x;
    }que[MAXN];
    struct Segment_Tree{
    	long long data[5];
    	int num,l,r;
    }a[MAXN<<2];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline void pushup(int rt){
    	NUM(rt)=NUM(LSON)+NUM(RSON);
    	for(int i=0;i<5;i++)DATA(rt,i)=DATA(LSON,i)+DATA(RSON,((i-NUM(LSON))%5+5)%5);
    }
    void buildtree(int l,int r,int rt){
    	LSIDE(rt)=l;RSIDE(rt)=r;NUM(rt)=0;
    	if(l>=r)return;
    	int mid=l+r>>1;
    	buildtree(l,mid,LSON);
    	buildtree(mid+1,r,RSON);
    }
    void update(int k,int c,long long v,int rt){
    	if(LSIDE(rt)==RSIDE(rt)){
    		DATA(rt,1)+=v;
    		NUM(rt)+=c;
    		return;
    	}
    	int mid=LSIDE(rt)+RSIDE(rt)>>1;
    	if(k<=mid)update(k,c,v,LSON);
    	else update(k,c,v,RSON);
    	pushup(rt);
    }
    void work(){
    	for(int i=1,x;i<=n;i++){
    		if(que[i].f==1){
    			x=lower_bound(lsh+1,lsh+m+1,que[i].x)-lsh;
    			update(x,1,que[i].x,1);
    		}
    		else if(que[i].f==-1){
    			x=lower_bound(lsh+1,lsh+m+1,que[i].x)-lsh;
    			update(x,-1,-que[i].x,1);
    		}
    		else cout<<DATA(1,3)<<endl;
    	}
    }
    void init(){
    	char ch[2];
    	n=read();
    	for(int i=1,x;i<=n;i++){
    		scanf("%s",ch);
    		if(ch[0]=='a'){
    			x=read();
    			lsh[++m]=que[i].x=x;
    			que[i].f=1;
    		}
    		else if(ch[0]=='d'){
    			x=read();
    			que[i].x=x;
    			que[i].f=-1;
    		}
    		else que[i].f=0;
    	}
    	sort(lsh+1,lsh+m+1);
    	m=unique(lsh+1,lsh+m+1)-lsh-1;
    	buildtree(1,m,1);
    }
    int main(){
    	init();
    	work();
        return 0;
    }
    

    其实还有一种更暴力的方法:

    $vector$大法好!

    各种$STL$乱搞就好。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    using namespace std;
    int n;
    vector<int> a;
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    void work(){
    	char ch[2];
    	n=read();
    	for(int i=1,x;i<=n;i++){
    		scanf("%s",ch);
    		if(ch[0]=='a'){
    			x=read();
    			a.insert(lower_bound(a.begin(),a.end(),x),x);
    		}
    		else if(ch[0]=='d'){
    			x=read();
    			a.erase(lower_bound(a.begin(),a.end(),x));
    		}
    		else{
    			long long ans=0;
    			for(int i=2;i<a.size();i+=5)ans+=a[i];
    			cout<<ans<<endl;
    		}
    	}
    }
    int main(){
    	work();
        return 0;
    }
    
  • 相关阅读:
    php apc
    nginx https
    js弹出确认框,挺全
    websocket nodejs
    nodejs express测试
    【C++】Mandelbrot集绘制(生成ppm文件)
    【Scheme】Huffman树
    【Scheme】符号求导
    【Scheme】树结构
    【Scheme】序列的操作
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/10629256.html
Copyright © 2011-2022 走看看