Picture
Subject to the effect
ion 1998
Seeking n (<= 5000) covering a perimeter pattern of rectangular (including holes), coordinate range[-10000,10000]
answer
One-dimensional discrete +2 tree line, but think carefully not enough space, time, reluctantly accepted
Then visually possible 1-dimensional scanning the line segment tree +?
Then even scan lines may over-bare, as in the following code
The total number of order of magnitude in terms of input O(n)
, sorting O(n log n)
, scanning process O(sum(len周长))
about 5000*20000*4
the upper limit [but USACO gave up,
So it is still a good segment tree?
From the implementation is concerned, the rectangular split into x and y directions, by counting the accumulated number of layers of each block boundary is determined
#include <bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
using namespace std;
const string filename = "picture";
void usefile(){
freopen((filename+".in").c_str(),"r",stdin);
freopen((filename+".out").c_str(),"w",stdout);
}
int N,ans=0;
// OX向和OY向的 线段分离处理,互不影响
tuple<int,bool,int,int> Lx[10010],Ly[10010]; // {位置idx坐标,结束边bool?,st->end}
int level[20010];
void Scan(tuple<int,bool,int,int> *L) {
sort(L,L+N);
rep(i,0,20001)
level[i]=0;
rep(i,0,N){
rep(j,get<2>(L[i]),get<3>(L[i])){
if (!get<1>(L[i])){
ans += level[j+10000]==0;
level[j+10000]++;
} else {
level[j+10000]--;
ans += level[j+10000]==0;
}
}
}
}
int main(){
usefile();
scanf("%d",&N);
rep(i,0,N){
int x1,x2,y1,y2;
scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
// OX 方向边
Lx[i*2] = {y1,false,x1,x2};
Lx[i*2+1] = {y2,true,x1,x2};
// OY 方向边
Ly[i*2] = {x1,false,y1,y2};
Ly[i*2+1] = {x2,true,y1,y2};
}
N*=2;
Scan(Lx);
Scan(Ly);
printf("%d\n",ans);
return 0;
}
Hidden Password
ACM South Eastern Europe -- 2003
Subject to the effect
String L (length <=100’000
)
To find the string, after the translation, the first letter of all the strings in the string lexicographically smallest index in the original string
As cba
All strings acb bac cab, (sorted), corresponding to the first letter of the first string of the original string 2 position (counting from 0)
answer
enumerate!
We first find the smallest letter sweep againO(n)
Then find the coordinates of the start of
Gradually increasing the length of the
So we have a recursive relationship, to ensure that after each increase in length, but also the rest of the current coordinate leaving only the smallest,
Therefore, when the length increases l
, we maintain the initial coordinates of the entire string, the length from 1
the l
smallest are lexicographically
So we have two ways to change the length
- +1
Assuming that all point to the length expansion does not belong to the current point of maintenance, then the length plus 1, retention, increase the minimum dot character
example abcabdzzzabc
All initial a
coordinates [0,3,9]
, length1
Expansion, expansion targets, respectively [1,4,10]
, are not currently being maintained point ( [0,3,9]
)
It is more elements, the whole is b, the length=1+1=2
Next, the goal is to expand [2,5,11]
, it is not a maintenance point
Compare characters, two abc
, one abd
, it becomes a maintenance point [0,9]
, length becomes=2+1=3
Further expansion, the expansion target [3,0]
, noting 0
that our current maintenance of [0,9]
the elements, so do not take +1
the program
- Multiply
Suppose characters aabbabbb,
After then find the smallest characters, starting coordinates left [0,1,4]
, once you found any expansion of a next ( [1,2,5]
) is to maintain a point, then double length, after deleting a point, in this case, the expansion of position not the smallest point coordinates directly removed.
Because we maintain == point from 1 to the length, the length of each is lexicographically smallest, so there is no point in the maintenance, are non lexicographically smallest, can be multiplied
Remove the right point because lexicographical point of expansion of the right to maintain a certain point greater than or equal to the left of the case by the arbitration ring of equal treatment
As discovered after an expansion 0
in a expansion is 1
, and 1
that we maintain the point, so the length of = 1*2
, 1
point deletion, 4
expansion is 5
then 5
not maintained, so the 4
point is also deleted, the last remaining Summing0
The problems described above: The starting point is at what point?
Assumptions string aaazzaaza
,
Obviously after the initial operating point has to be maintained[0,1,2,5,6,8]
Note that, if handled from left to right, in accordance with the above algorithm will become [0,6,8???]
, and the actual nature of the ring from the point of view, should be expected to get [1,6,8]
, which is the 8
position seen as [8,0,1,2]
the starting point of this paragraph.
Find here plus a parent node, find the left-most point to the point on the ring corresponding sense, look at the bottom of the function of the word is circle
,
Meanwhile, circle
here, if found, the entire ring saved dots, then only these points is equivalent to the ring on the lexicographic order, in accordance with the minimum desired title index In this case, the answer to that is taken
Space complexity, emmmm nothing to say, you can look at variables, maintained atO(n)
time complexity,
Each will multiply the number of points divided by at least 2, because a point to stay, then the first of its extension to the original point of maintenance, the need for maintenance and the next to disappear, so every time you want to stay a point, it must be deleted a point, the point will not be left there, it must leave the last half or less
O(n+n/2+n/4) = O(2n) = O(n)
Consideration of any length are +1, then each can perform limit is +1
sum(n*(1+1/2+...1/n))
As we all know this is an infinite series, so the time complexity infinite
Also from large O(12n)=O(n)
complexity,
Here is the fact, that these two interludes, some less so O(2n+12n)=O(n)
, (mathematical habits bother classification ranging discussions can be used on the line, so a stay equal)
To sum up time and space are met
char s[100010];
int sz=0;
bool pos[100010];
vector<int>p;
vector<int>q;
int L;
bool circle(int idx,int len,int &newidx){
newidx = (idx+L-len)%L;
while(newidx != idx){
if(!pos[newidx]){
(newidx+=len)%=L;
return false;
}else{
newidx = (newidx+L-len)%L;
}
}
while(newidx - L > 0){
newidx -= L;
}
printf("%d\n",newidx);
return true;
}
int main(){
usefile();
// 同步增长,冲突取前,倍增 其余删除(因为保证最小)
scanf("%d",&L);
while(sz<L){
scanf("%s",s+sz);
sz+=strlen(s+sz);
}
char minch = s[0];
rep(i,1,L){
minch = min(minch,s[i]);
}
rep(i,0,L){
if(s[i] == minch){
p.push_back(i);
pos[i]=true;
}
}
int l = 1;
while(p.size() > 1){
int state = 0; // 0 for +1, 1 for *2
minch = s[(p[0]+l)%L];
for(auto idx : p){
if(pos[(idx+l)%L] == true){
state = 1;
break;
}
minch = min(minch,s[(idx+l)%L]);
}
if(state == 0){
q.clear();
for(auto idx:p){
if(!pos[idx])continue;
if(s[(idx+l)%L] == minch){
q.push_back(idx);
}else{
pos[idx]=false;
}
}
p=q;
l++;
}else{
q.clear();
int startidx ;
int ret = circle(p[0],l,startidx);
if(ret){
return 0;
}
int pidx = 0;
for(pidx=0;pidx<p.size();pidx++){
if(p[pidx] == startidx){
break;
}
}
rep(i,pidx,p.size()){
int idx = p[i];
if(!pos[idx])continue;
if(pos[(idx+l)%L]){
q.push_back(idx);
pos[(idx+l)%L] = false;
}else{
pos[idx]=false;
}
}
rep(i,0,pidx){
int idx = p[i];
if(!pos[idx])continue;
if(pos[(idx+l)%L]){
q.push_back(idx);
pos[(idx+l)%L] = false;
}else{
pos[idx]=false;
}
}
p=q;
l*=2;
}
}
printf("%d\n",p[0]);
return 0;
}
Twofive
Subject to the effect
ion 2001
A到Y
Configuration arranged to meet these 25
letters are aligned 5*5
per row after matrix, monotonically increasing, for the legitimate
All legal arrangement, according to the dictionary sort order
Write a lexicographic converted to strings and string ID is lexicographically number reverse procedure
Try thinking
Look at the amount of data, I can not reckon on the actual size so the first to write a play table, (the upper bound is 25!
but there is a limit so I do not know whether it will reduce the
#include <bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
using namespace std;
const string filename = "twofive";
void usefile(){
freopen((filename+".in").c_str(),"r",stdin);
freopen((filename+".out").c_str(),"w",stdout);
}
int chars[30];
int vis[30];
int cnt = 0;
void print(){
cout<<endl;
rep(i,0,5){
rep(j,0,5){
cout<<char(chars[i*5+j]+'a')<<" ";
}
cout<<endl;
}
}
void gen(int idx){
if(idx%5==0){
rep(i,0,25){
if(vis[i] == 0){
vis[i]=1;
chars[idx] = i;
gen(idx+1);
vis[i]=0;
return ;
}
}
}
if(idx == 24){
cnt++;
chars[24]=24;
print();
return ;
}
int sti = chars[idx-1];
if(idx>5){
sti=min(sti,chars[idx-5]);
}
rep(i,sti+1,26-(5-idx%5)*(5-idx/5)){
if(vis[i])continue;
vis[i]=1;
chars[idx] = i;
gen(idx+1);
vis[i]=0;
}
}
int main(){
// usefile();
gen(0);
cout<<cnt<<endl;
return 0;
}
Run a bit about
7951237
a b c d e
f g h l n
i m k q w
j p o r u
s t v x y
Changes only to the above i
described order of magnitude, can not expect to hit the table
Next, we note that if we have a way to convert from a digital number corresponding to the word, you can find the corresponding word 2 points system
Similarly, if we find the word mapped to the number of methods, then two points (if you can, because this word did not seem half so good to do) can turn to find the numbers, so the analysis, any problem can be solved a corresponding
The idea is also a simple sorting, counting the number is deleted, then the ordered sequence = Total - it is smaller than the number of deleted
answer
Memory of + dp
If we fill in the number of small to large
So obviously, the end of the row number of the newly inserted row number has been inserted at the end of the number, also has been inserted, such as
a b e
c d f
g
h
i
j
Insertable position g右侧
ore右侧
So we have dp
dp[i0][i1][i2][i3][i4]
The first row represents 0 i0
th, 1 row i1
number ... first i4
case the number of rows, the number of remaining unfilled portion of the desired
Regardless of the particular, considering only the fundamental limitation of the subject, the satisfied ij >= i(j+1)
, because we put the order number, the number is not less than the upper row the next row
There transfer equation
dp[i0][i1][i2][i3][i4] = dp[i0-1][...]+dp[...][i1-1][...]+dp[...][i2-1][...]+dp[...][i3-1][...]+dp[...][i4-1]
Wherein if -1
not satisfied row when the magnitude relation between the number, then the corresponding directly dp0
In summary, we have no specific requirements in value can be calculated dp satisfy all topic under restrictions, 时间复杂度 = O(空间*状态转移)=O(6^5*5)
and spaceO(6^5)
Solving
The next question is how to seek conversion
Because idx are asking for the actual legal order twofive dictionary
Then we can approach by bit,//延伸阅读 BROP的按位枚举攻击方法
Suppose we are seeking
ADEFGBHIJKC...Y
, Then its lexicographical = AB...的所有
+ AC...的所有
+ ...
Simply put, if the prefix is a prefix length is less than the other requirements, then the number prefix plus all,
Etc. If the length of prefix value equal to the required prefix, the prefix length +
Prefix length for the outer layer, an intermediate for the letters, the time complexity is less than O(25*25)
Above we can be converted from a string to index
in contrast
The same method of approximation, it is possible O(25*25)
within the time complexity index into a string
#include <bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
using namespace std;
const string filename = "twofive";
void usefile(){
freopen((filename+".in").c_str(),"r",stdin);
freopen((filename+".out").c_str(),"w",stdout);
}
char s[100]; // 按位逼近的
char str[100]; // str2index
int dp[6][6][6][6][6];
int dfs(int a=0, int b=0, int c=0, int d=0, int e=0, char ch='A') {
if(ch > 'Y') return 1;
int &ret = dp[a][b][c][d][e];
if(ret) return ret;
// 每一行 一定小于等于上一行
int w = 5;
int *v[6]={&w,&a,&b,&c,&d,&e};
rep(i,1,6){
// 未填过 和 已经填过(按照 字母顺序扩展)
int idx = *v[i]+(i-1)*5;
if(*v[i] < *v[i-1] && (s[idx] == 0 || s[idx] == ch)){
(*v[i])++;
ret+=dfs(a,b,c,d,e,ch+1);
(*v[i])--;
}
}
return ret;
}
void index2word(){
int n;
scanf("%d",&n);
rep(i,0,25){
for(s[i] = 'A';; s[i]++) { // 按位逼近 时间复杂度25×25
memset(dp, 0,sizeof(dp));
int ret = dfs();
// cout<<i<<" = "<<s[i]<<"\tret = "<<ret<<endl;
if(ret >= n) break;
n -= ret;
}
}
printf("%s\n", s);
}
void word2index(){
scanf("%s", str);
int ans = 1;
rep(i, 0, 25) {
for(s[i] = 'A'; s[i] < str[i]; s[i]++) {
memset(dp, 0,sizeof(dp));
ans += dfs();
}
}
printf("%d\n", ans);
}
int main(){
usefile();
char c;
cin >> c;
if(c == 'N') { // index 2 word
index2word();
} else if(c == 'W') { // word 2 index
word2index();
}
return 0;
}
Dp The above process is implemented in alphabetical order filled by ch guaranteed, so that the outermost dp enumeration time, it directly from the A to the Y