• [POI2015]LOG


    题目

    发现询问是针对整个区间,也就是说位置什么用都没有

    发现我们需要构造出(s)个长度为(c)的数列,每个数只能在一个数列中出现一次,且一个数最多的使用次数是其大小

    对于那些大于等于(s)的数,我们让这些数在每一个数列里都出现就好了,如果这样的数有(val)个,相当于我们要构造的数列的长度变成了(c-val)

    对于小于(s)的数我们可以让这些数在每一个数列里尽量出现,看一下这些数的和是否能充满剩下的(s imes(c-val))个位置就好了

    树状数组维护一下就好了

    代码

    #include<algorithm>
    #include<cstdio>
    #define LL long long
    #define lowbit(i) ((i)&(-i))
    #define re register
    #define maxn 1000005
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    int n,m,sz;
    char opt[maxn][2];
    int a[maxn],b[maxn],c[maxn],pos[maxn];
    struct Bit {
    	LL t[maxn];
    	inline void add(int x,int val) {for(re int i=x;i<=sz;i+=lowbit(i)) t[i]+=val;}
    	inline LL ask(int x) {LL now=0;for(re int i=x;i;i-=lowbit(i)) now+=t[i];return now;}
    }B[2];
    inline int find(int x) {
    	int l=1,r=sz;
    	while(l<=r) {
    		int mid=l+r>>1;
    		if(c[mid]==x) return mid;
    		if(c[mid]>x) r=mid-1;else l=mid+1;
    	}
    	return 0;
    }
    int main() {
    	n=read(),m=read();
    	for(re int i=1;i<=m;i++) scanf("%s",opt[i]),a[i]=read(),b[i]=read(),c[i]=b[i];
    	std::sort(c+1,c+m+1),sz=std::unique(c+1,c+m+1)-c-1;
    	for(re int i=1;i<=m;i++) {
    		int x=find(b[i]);
    		if(opt[i][0]=='U') {
    			if(pos[a[i]]) B[0].add(pos[a[i]],-1),B[1].add(pos[a[i]],-1*c[pos[a[i]]]);
    			B[0].add(x,1),B[1].add(x,b[i]);pos[a[i]]=x;
    		}
    		else {
    			a[i]-=B[0].ask(sz)-B[0].ask(x-1);
    			if(a[i]<=0) {puts("TAK");continue;}
    			if(B[1].ask(x-1)>=(LL)a[i]*(LL)b[i]) puts("TAK");
    				else puts("NIE");
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    初涉网络安全领域
    pythontip上的数据结构和算法练习题
    学c++需要先学c语言吗?
    田园将芜胡不归
    java学习视频
    微软越来越喜欢Github(转载)
    指针(一级指针、二级指针)
    数字盒子
    点结构Tpoint
    枚举类型
  • 原文地址:https://www.cnblogs.com/asuldb/p/10540626.html
Copyright © 2020-2023  润新知