SRM 521

賽後做的這些題,值得一提的事div2的1000和div1的500

題意差不多,在平面上給你一些點,用正方形去圈這些點,在保證所圈的點集不同的情況下有多少個這樣的正方形。

div2 1000給你的正方形邊長是固定的,而div1 500邊長有一個範圍。

思路:首先要將給你的點得座標離散化,形成一個個網格,然後我需要利用這些格點來枚舉正方形;

這裏我沒有直接枚舉正方形,我先枚舉由這些格點構成的矩形,依次枚舉矩形的左下和右上點並判斷哪些點在矩形內,

並用位壓縮存入一個set裏,最後返回set的大小就是答案。

但問題是怎麼保證枚舉的這個矩形和包裹它的正方形一一對應?也就是說有可能存在另一個矩形包含同樣的點並且也在正方形內,怎麼判斷呢?

答案是我們在枚舉矩形的同時同時枚舉一個長寬都比它大的大一點的矩形,看是否被正方形包含。(詳見issqure函數)

div2 1000

bool isinrectange(int x0, int y0, int x1, int y1, int x, int y) //看點是否在矩形裏
{
    return (x0<=x&&x<=x1&&y0<=y&&y<=y1);
}

bool issqure(int n, int nx1, int ny1, int nx2, int ny2) //看這個矩形是否有唯一的正方形包裹他
{
    //n1是正常枚舉的矩形,n2是比它更大的矩形
    if(max(nx1,ny1)>n)return false;
    return (nx2>n&&ny2>n); //等於是不行的,如果等於肯定有比它大的矩形也能用同一個正方形包裹
}

long long SquaredSubsets::countSubsets(int n, vector <int> x, vector <int> y) {
	set<long long> ans;
	set<int>sx,sy;
	sx=set<int>(x.begin(),x.end()); sy=set<int>(y.begin(),y.end());
	sx.insert(INF); sx.insert(-INF); sy.insert(INF); sy.insert(-INF);
	vector<int> px, py;
	px=vector<int>(sx.begin(),sx.end());
	py=vector<int>(sy.begin(),sy.end());
	for(int xi = 1; xi < px.size(); xi++) for(int yi = 1; yi < py.size(); yi++)
	for(int xj = xi; xj < px.size()-1; xj++) for(int yj = yi; yj < py.size()-1; yj++)
	{
	    int x0 = px[xi], y0 = py[yi];
	    int x1 = px[xj], y1 = py[yj];
	    if(issqure(n, x1-x0, y1-y0, px[xj+1]-px[xi-1], py[yj+1]-py[yi-1]))
        {
            long long temp = 0;
            for(int i = 0; i < x.size(); i++)
            {
                if(isinrectange(x0,y0,x1,y1,x[i],y[i]))
                    temp |= ((1LL)<<i);
            }
            if(temp)ans.insert(temp);
        }
	}
	return ans.size();
}


div1 500

大部分過程和上題一致,但要注意的事正方形變成有範圍了;

那我們在枚舉矩形時先根據矩形邊長和正方形邊長確定一個最小的能夠包裹住矩形的正方形,,然後以這個正方形爲標準進行下面的判斷,詳見代碼:

bool isinrectange(int x0, int y0, int x1, int y1, int x, int y) //看點是否在矩形裏
{
    return (x0<=x&&x<=x1&&y0<=y&&y<=y1);
}

bool issqure(int nlow, int nhigh, int nx1, int ny1, int nx2, int ny2) //看這個矩形是否有唯一的正方形包裹他
{
    //n1是正常枚舉的矩形,n2是比它更大的矩形
    int size = max(nlow, max(nx1,ny1)); //size是能包裹這個矩形的最小正方形的邊長
    if(size>nhigh)return false;
    return (nx2>size&&ny2>size); //等於是不行的,如果等於肯定有比它大的矩形也能用同一個正方形包裹
}
long long RangeSquaredSubsets::countSubsets(int nlow, int nhigh, vector <int> x, vector <int> y) {
	set<long long> ans;
	set<int>sx,sy;
	sx=set<int>(x.begin(),x.end()); sy=set<int>(y.begin(),y.end()); //非常巧妙,以後對一個序列求不重複
	sx.insert(INF); sx.insert(-INF); sy.insert(INF); sy.insert(-INF);//的有序序列可以先將其存入一個
	vector<int> px, py;                                              //set,然後再存回來
	px=vector<int>(sx.begin(),sx.end());
	py=vector<int>(sy.begin(),sy.end());
	for(int xi = 1; xi < px.size(); xi++) for(int yi = 1; yi < py.size(); yi++) //i是左下點,j是右上點
	for(int xj = xi; xj < px.size()-1; xj++) for(int yj = yi; yj < py.size()-1; yj++)
	{
	    int x0 = px[xi], y0 = py[yi];
	    int x1 = px[xj], y1 = py[yj];
	    if(issqure(nlow, nhigh, x1-x0, y1-y0, px[xj+1]-px[xi-1], py[yj+1]-py[yi-1]))
        {
            long long temp = 0;
            for(int i = 0; i < x.size(); i++)
            {
                if(isinrectange(x0,y0,x1,y1,x[i],y[i]))
                    temp |= ((1LL)<<i);
            }
            if(temp)ans.insert(temp);
        }
	}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章