BZOJ4378: [POI2015]Logistyka

题解: 题意容易理解错 实质上这个题就是2种操作

1.单点修改

2.问是否每次操作能否选取c个大于等于1的 然后能否进行s次

首先很显然的 如果大于等于s的数量大于等于c 那么必然可行 如果小于等于c 那我们考虑剩下的总和是否大于等于(c-k)*s 如果大于则可行 否则则不可行

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=1e6+10;
const double eps=1e-8;
#define ll long long
using namespace std;
struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
ll read(){
	ll x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
	return x*f;
}


ll sum1[MAXN],sum2[MAXN],a[MAXN];
vector<ll>vec;
int sz;
int get_id(int x){return x&(-x);}
void update(int x,ll key){for(int i=x;i>0;i-=get_id(i))sum1[i]+=key;}
void update2(int x,ll key){for(int i=x;i>0;i-=get_id(i))sum2[i]+=key;}
ll Sum1(int x){ll ans=0;for(int i=x;i<=sz;i+=get_id(i))ans+=sum1[i];return ans;}
ll Sum2(int x){ll ans=0;for(int i=x;i<=sz;i+=get_id(i))ans+=sum2[i];return ans;}
typedef struct node{int op,x;ll y;}node;
node d[MAXN];

int main(){
	int n,m;n=read();m=read();char ch;
	vec.pb(0);
	inc(i,1,m){
		scanf(" %c",&ch);d[i].x=read();d[i].y=read();vec.pb(d[i].y);
		if(ch=='U')d[i].op=1;else d[i].op=2;
	}
	sort(vec.begin(),vec.end());
	sz=unique(vec.begin(),vec.end())-vec.begin();
	for(int i=1;i<=n;i++)a[i]=1;
	inc(i,1,m){
		d[i].y=lower_bound(vec.begin(),vec.begin()+sz,d[i].y)-vec.begin()+1;
		if(d[i].op==1){update(a[d[i].x],-1),update2(a[d[i].x],-vec[a[d[i].x]-1]),update(d[i].y,1),update2(d[i].y,vec[d[i].y-1]),a[d[i].x]=d[i].y;}
		else{
			ll ans1=Sum1(d[i].y);
			if(ans1>=d[i].x)puts("TAK");
			else {
				ans1=d[i].x-ans1;
				ll ans2=Sum2(1)-Sum2(d[i].y);
				if(ans2>=1LL*ans1*vec[d[i].y-1])puts("TAK");
				else puts("NIE");
			}
		}
	}
	return 0;
}

  

4378: [POI2015]Logistyka

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 643  Solved: 333
[Submit][Status][Discuss]

Description

维护一个长度为n的序列,一开始都是0,支持以下两种操作:
1.U k a 将序列中第k个数修改为a。
2.Z c s 在这个序列上,每次选出c个正数,并将它们都减去1,询问能否进行s次操作。
每次询问独立,即每次询问不会对序列进行修改。

Input

第一行包含两个正整数n,m(1<=n,m<=1000000),分别表示序列长度和操作次数。
接下来m行为m个操作,其中1<=k,c<=n,0<=a<=10^9,1<=s<=10^9。

Output

包含若干行,对于每个Z询问,若可行,输出TAK,否则输出NIE。

Sample Input

3 8
U 1 5
U 2 7
Z 2 6
U 3 1
Z 2 6
U 2 2
Z 2 6
Z 2 1

Sample Output

NIE
TAK
NIE
TAK

HINT

鸣谢Claris

原文地址:https://www.cnblogs.com/wang9897/p/9627063.html