zcmu-1957: 烏鴉坐飛機

1957: 烏鴉坐飛機
Time Limit: 2 Sec Memory Limit: 128 MB
Submit: 83 Solved: 6
[Submit][Status][Web Board]
Description
社會我福哥,爲了揍成龍去玩了玩集合。
n 個集合,每個集合有m 個數。
q 個詢問,每次詢問兩個數a,b ,問是否存在集合包含這兩個數。
Input
多組測試數據(10)
第一行一個n(1n1000)
接下來n 行,每行一個mi ,後面有mi 個數num . (1num,mi10000)
n+2 行一個整數q ,表示有q 次查詢(1q200000)
接下來q 行,每行兩個整數a,b .(1a,b10000)
Output
每組數據輸出q 行。存在輸出"Yes" ,否則輸出"No" (不包含雙引號)
Sample Input
3
3 1 2 3
3 1 2 5
1 10
4
1 3
1 5
3 5
1 10
Sample Output
Yes
Yes
No
No
HINT
因oj不支持markdown和tex.

若無法正確顯示tex數學公式,請使用google chrome瀏覽器並安裝math anywhere插件
【分析】
考慮一下數據範圍數字≤10000,集合數量≤1000,剛開始的思路是暴力標記,內存炸了,硬搜超時。。。後來看了大佬的思路應該用壓位。。。。
一個int可以存32位,那麼32*32=1024>1000,所以32個int就可以存下所有情況,那麼對讀取的每個數字x,用32個int記錄一下這個x出現在哪些集合過,然後對讀取的x,y對這32個int分別做一次與運算就可以知道是否同時存在某個集合中了,
壓位沒什麼好說的,每32個集合壓成一個int記錄
判斷的話也一樣,對對應的每一位
假設
當前a[x][i]==010100
當前a[y][i]中存在010000,那麼這兩個整數的&結果一定大於0,因爲其中有一位結果是1,也就是說只要x,y同時存在於某一個集合,那麼在那一位的&運算時結果一定1,那麼最終結果一定大於0,因爲與運算只有1&1=1…所以只有同時存在某一個集合中時運算結果纔會>0,反之如果運算結果>0,那麼x,y一定同時存在與某個集合`

#include <cstdio>  
#include <cstring>  
#include <cmath>  
#include <iostream>  
#include <algorithm>  
using namespace std;  
int a[10010][40];  
int main()  
{  
    int n;  
    while(~scanf("%d",&n))  
    {  
        memset(a,0,sizeof(a)); //清零; 
        for(int i=0;i<n;i++)  
        {  
            int m;
            scanf("%d",&m);  
            for(int j=0;j<m;j++)  
            {  
                int x;scanf("%d",&x);//因爲範圍是1-1000;小於1024;所以可以用32*32的存
                int pos=1<<(i%32);//右移i%32位;
                a[x][i/32]|=pos;//用'|'運算符記錄%32的位數;
            } 
        } 
        int q;scanf("%d",&q);  
        while(q--)  
        {  
            int x,y;scanf("%d%d",&x,&y);                  
            for( int i=0;i<=32;i++)
            {
                //應爲只有相同位置上都是1纔會是一,而相同位置上都是一則說明在同一個集合裏面;
                if(a[x][i]&a[y][i]){puts("Yes");break;}
                if(i==32)puts("No");
            }
        }  
    }  
    return 0;  
}  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章