POI2014(未完待续)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/baidu_36797646/article/details/84760222

Solar Panels:

简单题,直接分块对每种数判断是否合法就行了。

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
int read()
{
    int 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^48),ch=getchar();
    return x*f;
}
int main()
{
    int T=read();
    while(T--)
    {
        int l1=read(),r1=read(),l2=read(),r2=read();
        int l=max(l1,l2),r=min(r1,r2);
        if(l<=r){printf("%d\n",r);continue;}
        if(l1>l2)swap(l1,l2),swap(r1,r2);
        int pos,ans=1;
        for(int i=l1;i<=r1;i=pos+1)
        {
            int t1=l2/i,t2=r2/i,nl=min(r1,l2/(l2/i)),nr=min(r1,r2/(r2/i));
            pos=min(nl,nr);
            if(l2%i==0||t1!=t2)ans=i;
            if(l2%pos==0||t1!=t2)ans=pos;
        }
        if(ans!=1){printf("%d\n",ans);continue;}
        int cnt=0;
        for(int i=1;i<l1;i=pos+1)
        {
            cnt++;
            int tl1=l1/i,tr1=r1/i,nl1=min(l1-1,l1/(l1/i)),nr1=min(l1-1,r1/(r1/i));
            int tl2=l2/i,tr2=r2/i,nl2=min(l1-1,l2/(l2/i)),nr2=min(l1-1,r2/(r2/i));
            pos=min(min(nl1,nl2),min(nr1,nr2));
            if((l1%i==0||tl1!=tr1)&&(l2%i==0||tl2!=tr2))ans=i;
            if((l1%pos==0||tl1!=tr1)&&(l2%pos==0||tl2!=tr2))ans=pos;
        }
        printf("%d\n",ans);
    }
}

Little Bird:

考虑最简单的DP:
f i = f j ( D i &lt; D j ) f_i=f_j(D_i&lt;D_j) f i = f j + 1 ( D i &gt; = D j ) f_i=f_j+1(D_i&gt;=D_j)
看上去像单调队列的样子,但是无法解决括号内的限制。
但是由于后面的式子只会使答案+1,所以可以直接维护一个 f f 单调递增的单调队列,这样就可以保证队头的一定是最优的之一。
如果 f f 相等就保留 D D 大的。

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=1000010;
const int inf=2147483647;
int read()
{
    int 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^48),ch=getchar();
    return x*f;
}
int Q,n,k,D[Maxn],q[Maxn],head,tail,f[Maxn];
int main()
{
    n=read();
    for(int i=1;i<=n;i++)D[i]=read();
    Q=read();
    while(Q--)
    {
        k=read();
        head=tail=1;
        q[1]=1;f[1]=0;
        for(int i=2;i<=n;i++)
        {
            while(head<=tail&&q[head]<i-k)head++;
            f[i]=f[q[head]]+(D[q[head]]<=D[i]);
            while(head<=tail&&(f[q[tail]]>f[i]||(f[q[tail]]==f[i]&&D[i]>=D[q[tail]])))tail--;
            q[++tail]=i;
        }
        printf("%d\n",f[n]);
    }
}

Card:

水题,线段树直接维护区间内两个端点四种选择情况是否可行即可。

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=200010;
const int inf=2147483647;
int read()
{
	int 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^48),ch=getchar();
	return x*f;
}
int n,q,v[Maxn][2];
bool c[Maxn<<2][2][2];
void up(int x,int lc,int rc,int p)
{
	for(int i=0;i<2;i++)
	for(int j=0;j<2;j++)
	c[x][i][j]=false,
	c[x][i][j]|=
	(
	((v[p][0]<=v[p+1][0])&c[lc][i][0]&c[rc][0][j])|
	((v[p][0]<=v[p+1][1])&c[lc][i][0]&c[rc][1][j])|
	((v[p][1]<=v[p+1][0])&c[lc][i][1]&c[rc][0][j])|
	((v[p][1]<=v[p+1][1])&c[lc][i][1]&c[rc][1][j])
	);
}
void w(int x,int l,int r)
{
	if(l==r)
	{
		c[x][0][0]=c[x][1][1]=true;
		c[x][0][1]=c[x][1][0]=false;
		return;
	}
	int mid=l+r>>1,lc=(x<<1),rc=((x<<1)|1);
	w(lc,l,mid),w(rc,mid+1,r);
	up(x,lc,rc,mid);
}
void modify(int x,int l,int r,int p)
{
	if(l==r)return;
	int mid=l+r>>1,lc=(x<<1),rc=((x<<1)|1);
	if(p<=mid)modify(lc,l,mid,p);
	else modify(rc,mid+1,r,p);
	up(x,lc,rc,mid);
}
int main()
{
	n=read();
	for(int i=1;i<=n;i++)v[i][0]=read(),v[i][1]=read();
	w(1,1,n);
	q=read();
	while(q--)
	{
		int x=read(),y=read();
		swap(v[x][0],v[y][0]),swap(v[x][1],v[y][1]);
		modify(1,1,n,x),modify(1,1,n,y);
		if(c[1][0][0]||c[1][0][1]||c[1][1][0]||c[1][1][1])puts("TAK");
		else puts("NIE");
	}
}

猜你喜欢

转载自blog.csdn.net/baidu_36797646/article/details/84760222
今日推荐