(山东省第一届省赛 I 题) SDUTOJ 2159 Ivan comes again! (线段树+set)

题目地址:SDUT 2159

这题的数据很水。。几乎所有人都是水过去的。。网上也没找到正解,全是水过去的。于是我来第一发正解23333。

首先,可以想到的是先离线下来,然后对行离散化,然后对于每行的所有列用set去存,那么怎么去找最小的行有大于给出列的列数呢?这时候线段树就可以登场了,用线段树来维护每一行的出现的最大列,这样就可以用线段树去搜了。然后删除添加操作同时在set与线段树中完成。

代码如下:

#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <set>
#include <stdio.h>
using namespace std;
#define LL __int64
#define pi acos(-1.0)
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double eqs=1e-9;
const int MAXN=200000+10;
#define root 0, cnt, 1
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1
int Max[MAXN<<2], b[MAXN], c[MAXN], cnt;
set<int>st[MAXN];
struct node
{
        int x, y, z;
}fei[300000];
void PushUp(int rt)
{
        Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
}
void Update(int p, int x, int l, int r, int rt)
{
        if(l==r){
                Max[rt]=x;
                return ;
        }
        int mid=l+r>>1;
        if(p<=mid) Update(p,x,lson);
        else Update(p,x,rson);
        PushUp(rt);
}
int Query(int x, int ll, int l, int r, int rt)
{
        if(l==r){
                if(Max[rt]>=x) return l;
                else return -1;
        }
        int ans=-1, mid=l+r>>1;
        if(ll<=mid&&Max[rt<<1]>=x) ans=Query(x,ll,lson);
        if(ans!=-1) return ans;
        if(Max[rt<<1|1]>=x) ans=Query(x,ll,rson);
        return ans;
}
int BS(int x)
{
        int low=0, high=cnt, mid;
        while(low<=high){
                mid=low+high>>1;
                if(c[mid]==x) return mid;
                else if(c[mid]>x) high=mid-1;
                else low=mid+1;
        }
}
int BS1(int x)
{
        int low=0, high=cnt, mid, ans=-1;
        while(low<=high){
                mid=low+high>>1;
                if(c[mid]>x) {
                        ans=mid;
                        high=mid-1;
                }
                else low=mid+1;
        }
        return ans;
}
void init(int n)
{
        for(int i=0;i<n;i++){
                st[i].clear();
        }
        memset(Max,-1,sizeof(Max));
}
int main()
{
        int n, i, j, x, tot, ans, Case=0;
        char s[20];
        while(scanf("%d",&n)!=EOF&&n){
                cnt=tot=0;
                init(n);
                for(i=0;i<n;i++){
                        scanf("%s%d%d",s,&fei[i].x,&fei[i].y);
                        if(!strcmp(s,"add")){
                                fei[i].z=1;
                                b[tot++]=fei[i].x;
                        }
                        else if(!strcmp(s,"find")){
                                fei[i].z=2;
                        }
                        else fei[i].z=3;
                }
                sort(b,b+tot);
                c[0]=b[0];
                for(i=1;i<tot;i++){
                        if(b[i]!=b[i-1])
                        c[++cnt]=b[i];
                }
                printf("Case %d:\n",++Case);
                for(i=0;i<n;i++){
                        if(fei[i].z==1){
                                x=BS(fei[i].x);
                                st[x].insert(fei[i].y);
                                Update(x,*(--st[x].end()),root);
                        }
                        else if(fei[i].z==2){
                                x=BS1(fei[i].x);
                                if(x==-1) {
                                        puts("-1");
                                        continue ;
                                }
                                ans=Query(fei[i].y+1,x,root);
                                if(ans==-1) puts("-1");
                                else printf("%d %d\n",c[ans],*(st[ans].lower_bound(fei[i].y+1)));
                        }
                        else{
                                x=BS(fei[i].x);
                                st[x].erase(fei[i].y);
                                if(!st[x].size()){
                                        Update(x,-1,root);
                                }
                                else Update(x,*(--st[x].end()),root);
                        }
                }
                puts("");
        }
        return 0;
}
时间: 2024-10-11 12:33:06

(山东省第一届省赛 I 题) SDUTOJ 2159 Ivan comes again! (线段树+set)的相关文章

山东省第九届省赛G题game

题目是一个很像NIM博弈的一道dp问题,实际上就是利用了NIM博弈的结论,XOR为0 原题目的意思是给定n堆石头,可以取走0-d堆石头,问取走之后后手必胜(实际上就是xor为0的情况)的取法数目 就是利用dp,状态表示就是前i堆,取走j堆,xor值为k 初始化的的状态就是dp[i,0,0]=1: 转移方程为dp[i,j,k]=dp[i-1,j,k]+dp[i-1,j-1,k^val[i]]; 也就是由第i堆不取产生k的情况,和第i堆取走之后前i-1堆k^val[i]的值 计算所有堆的抑或值,这样

Sdut 2165 Crack Mathmen(数论)(山东省ACM第二届省赛E 题)

Crack Mathmen TimeLimit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描写叙述 Since mathmen take security very seriously, theycommunicate in encrypted messages. They cipher their texts in this way: for everycharacther c in the message, they replace c wit

北京大学信息工程学院雷凯副教授作为评委 参加中国深圳创新创业大赛第一届国际赛

4月13日上午,全球瞩目的中国深圳创新创业大赛第一届国际赛,在坪山区举办了互联网和移动互联网(信息科技).生物与生命科技.材料与能源(含节能环保)行业总决赛.我院副教授雷凯老师作为信息科技行业专家被列为此次比赛的评委之一. 大赛于2016年12月1日正式启动,共有1210个参赛者报名.大赛在澳大利亚悉尼.加拿大多伦多.德国慕尼黑.印度班加罗尔.以色列特拉维夫.日本东京.英国伦敦和美国硅谷举办了8场分站赛,分站赛晋级的74个项目于4月11日齐聚深圳参加五个行业总决赛. 大赛邀请到诺贝尔物理学奖获得

Sdut 2108 Alice and Bob(数学题)(山东省ACM第四届省赛D题)

题目地址:sdut 2608 Alice and Bob Alice and Bob Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 Alice and Bob like playing games very much.Today, they introduce a new game. There is a polynomial like this: (a0*x^(2^0)+1) * (a1 * x^(2^1)+1)*....

sdut 2603 Rescue The Princess(算是解析几何吧)(山东省第四届ACM省赛A题)

题目地址:sdut 2603 Rescue The Princess Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 Several days ago, a beast caught a beautiful princess and the princess was put in prison. To rescue the princess, a prince who wanted to marry the princess

Sdut 2416 Fruit Ninja II(山东省第三届ACM省赛 J 题)(解析几何)

Time Limit: 5000MS Memory limit: 65536K 题目描写叙述 Haveyou ever played a popular game named "Fruit Ninja"? Fruit Ninja (known as Fruit Ninja HD on the iPad and Fruit Ninja THD for NvidiaTegra 2 based Android devices) is a video game developed by Hal

山东省第六届省赛 H题:Square Number

Description In mathematics, a square number is an integer that is the square of an integer. In other words, it is the product of some integer with itself. For example, 9 is a square number, since it can be written as 3 * 3. Given an array of distinct

【NOIP模拟赛】天下神凡 动态开点线段树

这些圆一定是在同一水平面上的,由于他们没有相交,因此我们发现他们每个人与外界关系可以分为,1.存在并圈圈 2.存在圈圈并被割,因此我们把所有的圆都加1,把被割的在加1,就可以啦,因此我们开一个线段树,维护一段区间有没有被全部覆盖 #include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> #include <algorithm> #define R reg

线段树水题 #1077 : RMQ问题再临-线段树

#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> using namespace std; #define maxn 1000000 + 10 #define Lson L, mid, root<<1 #define Rson mid+1, R, root<<1|1 #define