zoukankan      html  css  js  c++  java
  • bzoj3141: [Hnoi2013]旅行

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3141

    思路:一道杂技题....证明杂技,写的也杂技,13年最神的题

    首先有一个结论

    设S为+1和-1的总和,记sum为后缀和(为什么是后缀?因为做的时候要判后面是还否有解)

    如果S!=0,那么ans=ceil(S/m)

    否则如果sum[i]==0的个数>=m则为0,否则为1

    证明及具体做法见一个详细的题解http://www.cnblogs.com/lazycal/p/3221342.html

    deque是不能用的....

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define min(x,y) ((a[x])<(a[y])?(x):(y))
    #define abs(a) (a>=0?a:-(a))
    const int maxn=500010;
    using namespace std;
    int n,m,a[maxn],tot,sum[maxn],cnt[maxn];char ch;
    void read(int &x){
    	for (ch=getchar();!isdigit(ch);ch=getchar());
    	for (x=0;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    }
    struct node{int l,r,x;}line[maxn<<1];
    struct Tline{
    	int head,tail,len;
    	Tline(){head=tail=len=0;}
    	bool empty(){return !len;}
    	int newnode(int l,int r,int x){line[++tot]=(node){l,r,x};return tot;}
    	int front(){return line[head].x;}
    	int back(){return line[tail].x;}
    	void pop_back(){tail=line[tail].l,len--;}
    	void pop_front(){head=line[head].r,len--;}
    	void push_back(int x){
    		if (!len) head=tail=newnode(0,0,x);
    		else line[tail].r=newnode(tail,0,x),tail=line[tail].r;
    		len++;
    	}
    	void push(int x){
    		while (len&&a[back()]>a[x]) pop_back();
    		push_back(x);
    	}
    }Q[maxn<<1],Qu[maxn<<1],*q=Q+maxn,*qu=Qu+maxn;//是后缀和为i的单调队列,存有哪些点的后缀和为i
    
    void work(){
    	int S=sum[1],d=S?(abs(S)-1)/m+1:cnt[1]<m;
    	cnt[n+1]=-1;
    	if (!d){
    		for (int i=1,j=2;i<m;i++){
    			for (;cnt[j+1]>=m-i;j++)
    				if (!sum[j+1]) q[0].push(j);
    			printf("%d ",a[q[0].front()]);
    			q[0].pop_front();
    		}
    	}
    	else{
    		for (int i=2;i<=n;i++) qu[sum[i]].push_back(i-1);
    		int last=0;a[n+1]=n+1;
    		for (int i=1;i<m;i++){
    			int ans=n+1;
    			for (int j=sum[last+1]-d;j<=sum[last+1]+d;j++){
    				if (ceil(1.0*abs(j)/(m-i))>d) continue;
    				for (;!qu[j].empty()&&n-qu[j].front()>=m-i;qu[j].pop_front())
    					if (qu[j].front()>last) q[j].push(qu[j].front());
    				for (;!q[j].empty()&&q[j].front()<=last;q[j].pop_front());
    				if (!q[j].empty()) ans=min(ans,q[j].front());
    			}
    			last=ans,printf("%d ",a[ans]);
    		}
    	}
    	printf("%d
    ",a[n]);
    }
    
    int main(){
    	read(n),read(m);
    	for (int i=1;i<=n;i++) read(a[i]),read(sum[i]),sum[i]=sum[i]?1:-1;
    	for (int i=n-1;i>=1;i--) sum[i]+=sum[i+1];
    	for (int i=n;i>=1;i--) cnt[i]=cnt[i+1]+(!sum[i]);
    	work();
    	return 0;
    }
    
    /*
    8  3
    
    2  1
    
    3  1
    
    4  1
    
    1  0
    
    5  0
    
    6  1
    
    7  1
    
    8  0
    */



  • 相关阅读:
    shell学习三十八天----运行顺序和eval
    开发新手教程【三】Arduino开发工具
    【Cloud Foundry】Cloud Foundry学习(四)——Service
    java调用oracle函数
    JDK动态代理
    Nginx 笔记与总结(8)Location:归纳总结
    机器学习从入门到放弃之决策树算法
    用数据分析进行品类管理
    用数据分析进行品类管理
    大数据分析过程中经常遇到那13个问题
  • 原文地址:https://www.cnblogs.com/thythy/p/5493484.html
Copyright © 2011-2022 走看看