Codeforces Gym 100203D Different vectors 最小表示法

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

题目大意:

有一组序列,询问能分成几组使得每一组中的序列都互成双射

做法:

  • 将每组序列接成环
  • 把每一个元素替换成上一次该元素出现的位置与现在的位置的距离
  • 将新的序列做一遍最小表示法
  • 将最小表示的序列加到set中
  • 最后答案即为set的大小

代码:

125489362015-08-1517:29:14NKWBTBD - Different vectorsGNU C++Accepted310 ms900 KB
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <cstring>
#include <set>
#include <map>
#define MAXN 20001
using namespace std;
int n,s;
struct minr{
    int v[110];
    friend bool operator <(const minr &a,const minr &b)
    {
        for(int i=0;i<=s;i++)
            if(a.v[i]!=b.v[i])
                return a.v[i]<b.v[i];
        return 0;
    }
}node;
int num[MAXN],str[MAXN];
set<minr>se;
map<int,int>m;
int MinimumRepresentation(int *s, int l)
{  
    int i=0,j=1,k=0,t;  
    while(i<l && j<l && k<l) 
    {  
        t=s[(i+k)>=l?i+k-l:i+k]-s[(j+k)>=l?j+k-l:j+k];  
        if(!t) k++;  
        else
        {
            if(t>0)i=i+k+1;  
            else j=j+k+1;  
            if(i==j)++j;  
            k=0;  
        }  
    }  
    return (i<j?i:j);  
}  
//最小表示法 
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&s);
        for(int i=0;i<n;i++)
        {
            m.clear();
            for(int j=0;j<s;j++)
            {
                scanf("%d",&num[j]);
                if(m.find(num[j])==m.end())str[j]=0;
                else str[j]=j-m[num[j]];
                m[num[j]]=j;
            }
            for(int j=0;j<s;j++)
            {
                if(m[num[j]]>j)str[j]=s-m[num[j]]+j;
                m[num[j]]=j;
            }
            int st=MinimumRepresentation(str,s);
            for(int j=st;j<s;j++)node.v[j-st]=str[j];
            for(int j=0;j<st;j++)node.v[s-st+j]=str[j];
            se.insert(node);
        }
        printf("%d\n",(int)se.size());
        se.clear();
    }
    return 0;
}
区间第K值带修改 分块 区间第K值带修改 Q:给定一个序列 1、查询一个L到R的区间内的第K大(小)值。2、修改一个值。 这道神题困扰了我很久,直到学了各种各样的算法才会会这道题。 先比较一下流行的算法的效率吧 对于一个长度为N的序列 暴力:对于一段查询区间每次进行快排。 时间复杂度: 单次查询:O(NlogN) 修改:O(1) 空间复杂度:O(N) 线段树套平衡树: 单次查询:O(log^3 N) 阅读详情

相关推荐

可并堆——左偏树 Leftist Heap

今天学习了左偏树,这是一个好理解而且好写的数据结构,和二叉堆一样可以在O(1)时间内取出优先级最高的值,O(logn)时间内删除优先级最高的值,不同的是如果要合并两个堆那么二叉堆就只能跪了。而左偏树能在O(logn)的时间内实现两个堆的合并。 左偏树有两个重要的性质, 1、树中每个元素小于或大于其父亲节点的值(堆性质) 2、定义节点的距离为当前节点向下到叶子节点最少所需的边数,叶子节点的距离

None 2997

CodeForces - 574C(思维+最小表示法

CodeForces - 574C 根据唯一分解定理每一个数都可以表示成(2p13p2~~~~~~~~~),因为可以每次可以乘无数个二或无数个3,所以只需要将每个数中含有的2和3全部除掉,只要剩下的部分相同就可以完成了。 #include<iostream> #include<vector> #include<cstdio> #include<cstri...

霜雨蓝焰的博客 311

Codeforces Gym 100203D Different vectors 想法题 + Hash

题目大意: 就是现在给出N个向量, 对于两个向量他们相等的条件是可以通过轮转使得存在正整数之间的双射使得两者相等 给出N个向量问不相等的向量有多少个 大致思路: 首先对于每个向量, 先求出对于每个位置向左边(或者向右边)最近的和它相同的位置到这个位置的距离作为这个位置的新值 例如 1 2 2 3向左找的话就是 4 3 1 4, 只要两个向量这么变化之后通过轮转是一样的话就一定恩那

Gatevin的专栏 588

Codeforces 496B Secret Combination(最小表示法

题目链接:Codeforces 496B Secret Combination代码#include <cstdio> #include <cstring> #include <algorithm>using namespace std; const int maxn = 1005;int N; char S[maxn], T[maxn], F[maxn];int miniexpress(char*

不慌不忙、不急不躁 904

codeforces-559B-Equivalent Strings

codeforces-559B-Equivalent Strings

Linoy 1180

Codeforces 635B Island Puzzle【最小表示法+思维】

B. Island Puzzle time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output A remote island chain contains n islands, labeled 1

mengxiang000000 660

codeforces(559B)--B. Equivalent Strings(暴搜 或 最小表示法)

B. Equivalent Strings time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Today on a lecture about strings Gera

随风的专栏 2045

Noip 2013 Day1 T3 货车运输 启发式并查集树

题目大意:给一个图,求最大生成树,询问生成树上两个结点路径上最小的边权,若两点不可达输出-1。 这道题是很明显的LCA问题可以倍增写(详见http://blog.csdn.net/nkwbtb/article/details/21880941), 但是我今天看了看题解,惊奇地发现了一种极其美妙的做法。 就是启发式并查集树。 名字听起来非常高大上,实际上很简单,启发式并查集,就是维护每个集合

None 2334

Codeforces Gym 100379L Game with a string 博弈+交互题

题目大意:有26堆石子,你可以选其中的若干堆取走每个选定堆中的一颗石子,没法取的人失败。你需要选择先手和后手,然后与程序交互,给出必胜的方案。做法: 我们先看只有一堆的情况,如果这一堆中的石子数为偶数,那么先手必败,反之如果是奇数,那么先手必胜; 我们可以推广到26堆的情况,如果不存在奇数堆的石子那么先手必败,否则先手必胜。 至此,我们得到了一个最优方案。如果不存在奇数堆的石子那么我们选则后手,否则

None 2132

【LCA】最近公共祖先问题Lowest Common Ancestors

昨天集训出了一道LCA的题目,我只会写暴力然后不知道为啥崩栈了,然后想起了去年NOIP Day1 T3 也是不会LCA就废了,然后就没有然后了.....于是我今天学习了各种LCA的做法。 LCA:对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u、v的祖先且x的深度尽可能大。——百度百科 举个例子: 3和4节点的LCA就是2,2和6号节点的LCA

None 2090

POJ 2010 Moo University - Financial Aid (优先队列/二分答案)

题目大意:从c个物品中选出n(奇数)个物品,使得这n个物品的价值中位数尽量高,且总价格不超过f。做法1: 把物品按价值排序 half表示n/2向下取整 low[i]表示前i - 1个物品中价格最小的half个物品的价格和 hei[i]表示i之后的物品中价格最小的half个物品的价格和 low和hei可用优先队列维护 枚举中间物品即可 代码 NKWBTB Accepted 2592KB

None 1516

Codeforces Gym 100342F Move to Front 平衡树

题目大意:有一个链表其中的元素为1->2->3->4->…….->INF,每次询问一个元素在链表中的位置,然后把该元素放到链表的首位置。做法:beta version 如果输入数字不大,那么我们可以直接先把1到最大数字打上时间戳加到平衡树(按时间戳从新到老排序)里面去; 每次询问,就询问时间戳在平衡树中的rank即可; 在平衡树中删除该时间戳,将该数重新打上一个新的时间戳加入到平衡树中即可(相当于移

None 1466

Codeforces Gym 100971M Decomposition into Good Strings DP+数据结构

题目大意:定义有k个不同的字符的字符串为好字符串。现在给出一个字符串,求解对该字符串的每个前缀Si至少是多少个好字符串的连接,若不能由好字符串连接而成则输出-1。 例:k = 2 abac至少是ab和ac这两个好字符串的连接。 字符串长度<=2e5做法:一个比较直观的dp方程是这样的 f[i]表示Si的答案 f[i] = min(f[j] + 1) (j < i且Sj + 1…i是好字符串

None 1257

HDU 5412 区间第K值 带修改 树状数组套平衡树

题意:给定一个序列,两种操作:1、求修改第i个数为Vi;2、求区间[L,R]第K大的值。 2015多校练习赛的一道题。因为是经典题所以很多人都直接把模板敲上去了,然而通过率却惨不忍睹。我也是直接套以前写的程序的SB之一。然而分块时间复杂度太高并不能通过本题(分块做法见:http://blog.csdn.net/nkwbtb/article/details/21639647)于是愉快的TLE了。考

None 1156

URAL 1779 The Great Team 构造题

题目大意:要求构造一个n个点的无向图,使得不存在>=3个点的度数一致构造方法: 这题有很多构造方法; 既然不存在>=3个点的度数一致,那么我们使得相同度数的点都只有2个; 不妨画一画观察一下 - 我们值观察4、6、8的构造的话会发现,如果我们4个一组,每个组中的最后两个点连一条边,然后最后这两个点分别隔一个点向前面的点各连一条边,这样就形成一组合法的构造方案。因为它使前面的点的度数都增加了1,同时

None 1122

HDU 5381 The sum of gcd 离线处理+线段树

题意:给一组序列,多次询问,每次询问f(l,r)=∑ri=l∑rj=igcd(ai,ai+1....aj)f(l,r)=\sum_{i=l}^{r}\sum_{j=i}^{r}gcd(a_i,a_{i+1}....a_{j})最初在赛场上看到这道题的时候,就想离线处理,但是怎么也不会。原因是当时并不知道这题的一个性质:从一个下标为i的数向后的连续区间[i,i+1]、[i,i+2]...[i,n][i

None 1049

HDU Boring counting 4358 莫队算法

题目大意:给一颗N个节点的树,每个节点上有一个颜色。给出Q组询问,每次询问一个子树上恰好出现K次的颜色的个数。做法: - 将树DFS一遍,记下时间戳,得到每个子树dfs序的对应区间,并将颜色离散化。 - 记下每个询问,将询问子树变成询问区间,将区间左端点除以n−−√\sqrt n排序,在同一块的询问按右端点排序。 - 接着按莫队算法移动区间,得到对应答案。 1435

None 952

Codeforces Gym 100342J Triatrip Bitset+枚举

题目大意:给一个有向图(n<=1500),问有多少个三元环。做法: 用bitset保存每个点能到的点以及能到某个点的所有点 对每个点(记为U)逐一枚举,再枚举该点能到达的点(记为V) 将能到U点的bitset与V能到的点的bitset取交集,答案+=交集大小 最终答案÷3即可 时间复杂度O(n3)O(n^3),但是bitset将常数除以了32所以足够通过本题。 4543664 WHU_FFT

None 930

Codeforces Gym 100341I Hungry Queen 2 Set+模拟

题目大意:在一个无穷大的棋盘上有一个皇后在(0,0)点,皇后可以上下左右或者沿对角线移动。有n个卒,皇后要按卒的输入顺序吃卒,每次移动必须吃掉一个卒,皇后不能跳过卒。问皇后最多能吃掉几个卒?做法: 先将所有卒的位置(x、y、x+y、x-y)离散化; 用set分别记录,在同一行(按y排序)、同一列(按x排序)、同一对角线的卒; 模拟皇后的移动,每次在当前位置与下一个卒的位置所确定的set中查找下一个卒

None 925
上一篇: URAL 1779 The Great Team 构造题
下一篇: Codeforces Gym 100379L Game with a string 博弈+交互题
NKWBTB
博客等级 码龄16年 4粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值