• [POI2015]LOG(树状数组)


    今天考试考了这题,所以来贡献([POI2015]LOG)的第一篇题解。代码略丑,调了快三个小时才调出来(AC)代码。

    对于这种小清新数据结构题,所以我觉得树状数组才是这道题的正确打开方式。

    首先离散化,这样才不会爆内存。开两个树状数组,第一个树状数组记录离散化后(1)(i)中数字出现的个数,第二个树状数组离散化前(1)(i)数字出现值的和。把所有询问都读入进来,对于每次操作:

    操作(1):单点修改,若之前的数是正数,第一个树状数组(-1),第二个树状数组(-)原来的数,若之后的数是正数,第一个树状数组(+1),第二个树状数组(+)之后的数

    操作(2):区间询问,先将大于(s)的个数求出来,再比较(c-)大于(s)的个数乘上(c)与剩余数之和,若前者大,输出(NIE),否则输出(TAK)

    再开一个数组记录当前序列的值,就完事了

    (Code Below:)

    #include <bits/stdc++.h>
    #define ll long long
    #define res register
    using namespace std;
    const ll maxn=1000000+10;
    ll n,m,a[maxn],b[maxn],mp[maxn],tot,num;
    //a[i]是目前的序列情况,b[i]是第几次修改后离散化1-num,mp记录离散化后的数组1-1e9
    //tot是几次修改,num是离散化后的修改,c1[i]是1-i的个数,c2[i]是1-i的值的和 
    ll c1[maxn],c2[maxn];
    struct node{
    	ll k,x,id;
    }q[maxn];
    //id是第几次修改 
    inline ll read(){
    	res ll x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return (f==1)?x:-x;
    }
    ll lowbit(ll x){return x & (-x);}
    void add_num(ll x,ll y){
    	for(;x<maxn;x+=lowbit(x))
    		c1[x]+=y;	
    }
    void add_sum(ll x,ll y){
    	for(;x<maxn;x+=lowbit(x))
    		c2[x]+=y;
    }
    ll query_num(ll x){
    	ll ans=0;
    	for(;x>0;x-=lowbit(x))
    		ans+=c1[x];
    	return ans;
    }
    ll query_sum(ll x){
    	ll ans=0;
    	for(;x>0;x-=lowbit(x))
    		ans+=c2[x];
    	return ans;
    }
    
    int main()
    {
    	n=read(),m=read();
    	res ll k,x,c,s;char ch=getchar();
    	for(ll i=1;i<=m;i++){
    		while(ch!='U'&&ch!='Z') ch=getchar();
    		q[i].k=read(),q[i].x=read();
    		if(ch=='U') {
    			q[i].id=++tot;
    			b[tot]=mp[tot]=q[i].x;
    		}
    		else q[i].id=-1;
    		if(i!=m) ch=getchar();
    	}
    	sort(mp+1,mp+tot+1);
    	num=unique(mp+1,mp+tot+1)-mp-1;
    	for(ll i=1;i<=tot;i++)
    		b[i]=lower_bound(mp+1,mp+num+1,b[i])-mp;
    	for(ll i=1;i<=m;i++)
    		if(q[i].id!=-1) q[i].x=b[q[i].id];
    	for(ll i=1;i<=m;i++){
    		if(q[i].id!=-1){//q[i].x被离散化 
    			if(a[q[i].k]>0){
    				ll real=lower_bound(mp+1,mp+num+1,a[q[i].k])-mp;
    				add_num(real+1,-1);
    				add_sum(real+1,-a[q[i].k]);
    			}
    			a[q[i].k]=mp[q[i].x];
    			if(mp[q[i].x]>0){
    				add_num(q[i].x+1,1);
    				add_sum(q[i].x+1,mp[q[i].x]);
    			}
    		}
    		else {//q[i].x没被离散化,real是去q[i].x在mp中的位置 
    			ll real=upper_bound(mp+1,mp+num+1,q[i].x)-mp-1;
    			ll bigans=query_num(maxn+1)-query_num(real+1);
    			ll smallans=query_sum(real+1);
    			if(smallans>=(q[i].k-bigans)*q[i].x) printf("TAK
    ");
    			else printf("NIE
    ");
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Harvest of Apples (HDU多校第四场 B) (HDU 6333 ) 莫队 + 组合数 + 逆元
    BZOJ4383/LuoGuP3588 Pustynia/PUS 线段树建图优化
    初识splay
    nowcoder牛客wannafly挑战赛20
    初识树链剖分
    二维数据结构---线段树
    初识莫队——小Z的袜子
    kuangbin带我飞QAQ 并查集
    十个二分九个错?教你如何优雅地写二分查找
    Codeforces Round #436 (Div. 2) E. Fire(dp 记录路径)
  • 原文地址:https://www.cnblogs.com/owencodeisking/p/9534903.html
Copyright © 2020-2023  润新知